bfs
坑点很多的一题(由于一本通的辣鸡翻译会错题意*n)。
1.多组数据
2.如果某方向上没有不同字符光标不会动
我们每次预处理出每个点向四个方向下次到达的点。然后跑bfs即可
注意bfs每次只能扩展一层(也就是说距离dis每次最多只能+1,否则无法保证最优性)!(所以不要把移动和选择写到一起qwq)
处理字符用map就好了
(卡了我一整天qwq)
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> #include<map> using namespace std; inline int mini(int &a,int &b) {return a<b ?a:b;} int d1[4]={0,1,0,-1}; int d2[4]={1,0,-1,0}; int n,m,len,a[52][52],b[10002],vis[52][52]; struct data{int x,y,step,dis;}dir[4][52][52]; map <char,int> Map; void draw(){ //字符处理成数字好写 for(int i=0;i<=9;++i) Map[(char)('0'+i)]=i+1; for(int i=0;i<26;++i) Map[(char)('A'+i)]=i+11; Map['-']=37; Map['*']=38; } void pretreatment(){ //预处理四个方向上下次可到的点 for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) for(int k=0;k<4;++k){ int r1=i,r2=j; while(a[r1][r2]==a[r1+d1[k]][r2+d2[k]]) r1+=d1[k],r2+=d2[k]; dir[k][i][j]=(data){r1,r2,0,0}; } } inline int bfs(){ memset(vis,0,sizeof(vis)); queue <data> h; int ans=0; int k=1; while(b[k]==a[1][1]&&k<=len) ++k; h.push((data){1,1,k,k-1}); vis[1][1]=k; //特判在起点选取的情况 while(!h.empty()){ data u=h.front(); h.pop(); if(a[u.x][u.y]==b[u.step]){ //选择(千万不能和移动写在一起) if(u.step==len) {ans=u.dis+1; break;} vis[u.x][u.y]=u.step+1; h.push((data){u.x,u.y,u.step+1,u.dis+1}); continue; } for(int i=0;i<4;++i){ data to=dir[i][u.x][u.y]; to.x+=d1[i]; to.y+=d2[i]; //由于我的预处理没写完整要再加一次 if(to.x<1||to.x>n||to.y<1||to.y>m) continue; if(vis[to.x][to.y]>=u.step) continue; vis[to.x][to.y]=u.step; h.push((data){to.x,to.y,u.step,u.dis+1}); } } return ans; } int main(){ //freopen("UVA1714.in","r",stdin); draw(); char q[10002]; while(scanf("%d",&n)!=EOF) //多组数据 { scanf("%d",&m); for(int i=1;i<=n;++i){ scanf("%s",q); for(int j=0;j<m;++j) a[i][j+1]=Map[q[j]]; } scanf("%s",q); len=strlen(q); for(int i=0;i<len;++i) b[i+1]=Map[q[i]]; b[++len]=38; //b数组存操作串 pretreatment(); printf("%d ",bfs()); } return 0; }