标签:上下左右 har lse out keyboard 虚拟 main 处理 范围
题目描述
给出一个虚拟键盘,键盘上有一光标,可以上下左右移动,移动时沿该方向一直移动到不同字符,求将给定字符串输出的最小步数(初始位置在左上角,移动为一步,点击键盘为一步,字符串结尾有换行符,用‘*’表示)。
思路
首先每一步移动时都可能会移动多步,而数据范围又比较小,所以我们可以先预处理出从(i,j)位置出发沿四个方向所移动的步数。接下来就开始bfs。不过这道题的特殊之处是我们需要存储两个量,表示到(i,j)这个位置经过step步最多能输出多少个给定的字符。这样我们就可以用一个数组来存到(i,j)最多完成几个字符的输出,就可以减少不必要的求解。而对于目前所在的位置就是要输出的字符特殊处理一下即可。
代码
#include <bits/stdc++.h> using namespace std; struct aa { int x,y,step,num; aa(int x=0,int y=0,int step=0,int num=0):x(x),y(y),step(step),num(num){} }; int dx[5]={1,-1,0,0},dy[5]={0,0,1,-1}; int v[60][60],a[60][60][5]; char goal[10100],key[60][60]; queue<aa> q; int main() { int len,ans,r,c; scanf("%d%d",&r,&c); for(int i=1;i<=r;i++) scanf(" %s",key[i]+1); scanf(" %s",goal+1); goal[strlen(goal+1)+1]=‘*‘; len=strlen(goal+1); for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) for(int k=0;k<4;k++) { int nx=i,ny=j,t=0; while(nx>0&&nx<=r&&ny>0&&ny<=c) { if(key[nx][ny]!=key[i][j])break ; nx+=dx[k];ny+=dy[k];t++; } if(nx>0&&nx<=r&&ny>0&&ny<=c) a[i][j][k]=t; //从(i,j)沿k方向要走多少步 } v[1][1]=1; //到(i,j)最多输出多少字符 q.push(aa(1,1,0,1)); while(!q.empty()) { aa nex,now=q.front();q.pop(); // cout<<now.x<<‘ ‘<<now.y<<‘ ‘<<goal[now.num]<<endl; if(key[now.x][now.y]==goal[now.num]&&v[now.x][now.y]<now.num+1) { // cout<<now.x<<‘ ‘<<now.y<<‘ ‘<<goal[now.num]<<endl; v[now.x][now.y]=now.num+1; nex=aa(now.x,now.y,now.step+1,now.num+1); if(nex.num>len){ans=nex.step;break ;} q.push(nex); } else { for(int i=0;i<4;i++) { int bias=a[now.x][now.y][i]; if(bias) { nex=aa(now.x+bias*dx[i],now.y+bias*dy[i],now.step+1,now.num); // cout<<nex.x<<‘ ‘<<nex.y<<‘ ‘<<goal[nex.num]<<endl; if(nex.num<=v[nex.x][nex.y])continue ; v[nex.x][nex.y]=nex.num; q.push(nex); } } } } printf("%d",ans); return 0; }
标签:上下左右 har lse out keyboard 虚拟 main 处理 范围
原文地址:https://www.cnblogs.com/fangbozhen/p/11615882.html