【广搜】Keyboarding

匿名 (未验证) 提交于 2019-12-02 23:49:02

题目描述

给定一个r行c列的在电视上的“虚拟键盘”,通过“上,下,左,右,选择”共5个控制键,你可以移动电视屏幕上的光标来打印文本。一开始,光标在键盘的左上角,每次按方向键,光标总是跳到下一个在该方向上与当前位置不同的字符,若不存在则不移动。每次按选择键,则将光标所在位置的字符打印出来。
现在求打印给定文本(要在结尾打印换行符)的最少按键次数。

输入

第一行输入 r,c。
接下来给出一个 r×c的键盘,包括大写字母,数字,横线以及星号(星号代表 Enter 换行)。
最后一行是要打印的文本串 S,S 的长度不超过 10000。

输出

输出打印文本(包括结尾换行符)的最少按键次数。保证一定有解。

样例输入

2 19 ABCDEFGHIJKLMNOPQZY X*****************Y AZAZ 

样例输出

19 

提示

对于100%的数据,1≤r,c≤50,S的长度不超过10000。



【题解】

这个题目需要大家耐心处理细节,预处理所有点的四个方向能到达的地方。

然后用BFS搜索,注意搜索的顺序,已经利用好vis标记数组来记录。

  1 #pragma GCC optimize("Ofast") //编译环境优化   2 #include<bits/stdc++.h>   3 using namespace std;   4 const int N = 52 ;   5 const int M = 1e5+10;   6 const int P = 300;   7 char s[M];   8 int n,m,len;   9 int Map[P],vis[N][N];  10 int a[N][N],b[M];  11 typedef struct Node{  12     int x,y,step,dis;  13 }Node ;  14 Node F[N][N][4];  15   16 int dir[4][2]={  17        {-1,0},  18     {0,-1},{0,1},  19         {1,0}  20 };  21 void read_Char(char s[]){  22     int len = 0 ;  23     char c = getchar() ;  24     while ( c!='\n' ){  25         s[len++] = c;  26         c = getchar();  27     }  28     s[len] = '\0';  29 }  30 void _Map(){  31     for(int i=0;i<=9;i++){  32         Map[char('0'+i)] = i+1;  33     }  34     for (int i=0;i<26;i++){  35         Map[char('A'+i)] = i+11;  36     }  37     Map['-'] = 37 ;  38     Map['*'] = 38 ;  39 }  40 //预处理,处理每一个方向能到达的位置  41 void Init(){  42     for(register int i=1;i<=n;i++){  43         for(register int j=1;j<=m;j++){  44             for(register int k=0;k<4;k++){  45                 int tx = i,ty = j ;  46                 while( a[i][j] == a[tx+dir[k][0]][ty+dir[k][1]] )  47                     tx += dir[k][0] , ty += dir[k][1];  48                 F[i][j][k] = (Node) {tx,ty,0,0};  49             }  50         }  51     }  52 }  53 int BFS(){  54   55     memset(vis,0,sizeof(vis));  56     int k = 1 ;  57     //处理左上角就是目标的输出  58     while ( a[1][1] == b[k] && k<=len ) k++ ;  59     queue <Node> Q;  60     Q.push( (Node){1,1,k,k-1} ) ;  61     vis[1][1] = k ;  62     while( !Q.empty() ){  63   64         Node cur = Q.front();  65         //printf("(%d,%d)\n",cur.x,cur.y);  66         Q.pop();  67         //如果找到合适的位置则"选择"  68         if( a[cur.x][cur.y] == b[cur.step] ){  69             if( cur.step == len ){  70                 return cur.dis + 1 ;  71             }  72             vis[cur.x][cur.y] = cur.step + 1 ;  73             Q.push( (Node) { cur.x,cur.y,cur.step+1,cur.dis+1} ) ;  74             continue ;  75         }  76         //四个方向  77         for(int i=0;i<4;i++){  78             Node Next = F[cur.x][cur.y][i] ;  79             Next.x += dir[i][0];  80             Next.y += dir[i][1];  81   82             if( !(1<=Next.x && Next.x<=n && 1<=Next.y && Next.y<=m) ){  83                 continue;  84             }  85             //if( a[cur.x][cur.y] == a[Next.x][Next.y] ) continue;  86             // 如果后面剪枝过的  87             if( vis[Next.x][Next.y] >= cur.step ) continue ;  88             vis[Next.x][Next.y] = cur.step ;  89             Q.push((Node){Next.x,Next.y,cur.step,cur.dis+1} );  90         }  91     }  92 }  93 int main()  94 {  95     _Map();  96     //while( cin >> n >> m ){  97     while(~scanf("%d%d",&n,&m)){  98         //memset(a,'\0',sizeof(a));  99         for(register int i=1;i<=n;i++){ 100             scanf("%s",s+1); 101             //cin >> s+1 ; 102             for(register int j=1;j<=m;j++){ 103                 a[i][j] = Map[s[j]]; 104             } 105         } 106         scanf("%s",s+1); 107         //cin >> s+1 ; 108         len = strlen(s+1); 109         for(register int i=1;i<=len;i++){ 110             b[i] = Map[s[i]]; 111         } 112         b[++len] = Map['*']; 113         Init(); 114         printf("%d\n",BFS()); 115         //cout << BFS() << endl; 116     } 117     return 0; 118 } 119 /* 120 2 19 121 ABCDEFGHIJKLMNOPQZY 122 X*****************Y 123 AZAZ 124 */
Keyboarding

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!