zoukankan      html  css  js  c++  java
  • 【广搜】Keyboarding

    题目描述

    给定一个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标记数组来记录。

     这个题目是真的需要小心,很多坑。

    需要设定一个结构体,这个结构体需要提供记录  当前的坐标(x,y),匹配到下标 step,当前结点的花费的操作次数 dis

    1、预处理所有位置的四个方向的下一个位置是什么?

    2、设置标准的BFS框架,其中入队列之前,可以预处理左上角就是目标串的字符。

    3、进入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!='
    ' ){
     25         s[len++] = c;
     26         c = getchar();
     27     }
     28     s[len] = '';
     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)
    ",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,'',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
    ",BFS());
    115         //cout << BFS() << endl;
    116     }
    117     return 0;
    118 }
    119 /*
    120 2 19
    121 ABCDEFGHIJKLMNOPQZY
    122 X*****************Y
    123 AZAZ
    124 */
    Keyboarding
  • 相关阅读:
    让网页活起来!韵律线带你提升带你飞!
    打造晶格化背景
    简单banner制作
    设计模式-适配器模式
    类、方法的单一职责
    .NET趋势
    C# Delegate Event
    VB.NET项目技术总结
    版本控制工具Git的使用
    delete语句要注意的BUG.
  • 原文地址:https://www.cnblogs.com/Osea/p/11215807.html
Copyright © 2011-2022 走看看