2 1234 2144 1111 9999
2 4
这个题,直接使用BFS爆搜是能够过得,31ms
这个题被挂在了我们学校的OJ,数据被一些邪恶的学弟们加强了。。我用了BFS然后果断TLE
题目链接:http://220.166.52.162/oj/showproblem?problem_id=2360
后来得知,需要使用双向BFS。很可惜,自己从未写过双向BFS。于是又跑到网上去看双向BFS的资料。总算看明白了。。(退役的半年里,第一次学习新的算法)
其实思路还是挺简单的,双向就是利用两个BFS拼在一起,一个从起点开始搜索,一个从终点开始搜索
当两个BFS搜索的轨迹有重合的部分的时候,立即停止两个BFS,并根据当前重合点的与两个BFS已得到的信息来计算答案。
贴下代码:(双向BFS也写的很挫,把队列换成数组之后才1000ms卡过去了,当然在HDU上是0ms)
#include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<stdlib.h> using namespace std; int A[5],B[5],aim; int flag[10000]; int ak[10000]; int bk[10000]; struct node { int num; int step; }; void bfs() { memset(flag,0,sizeof(flag)); node k1,k2,k3,k4; int tmp[5],i,now[5],mt; node q1[10000]; node q2[10000]; int h1=0,t1=0,h2=0,t2=0; k1.num=A[1]*1000+A[2]*100+A[3]*10+A[4]; flag[k1.num]=1; ak[k1.num]=0; k1.step=0; k3.num=B[1]*1000+B[2]*100+B[3]*10+B[4]; k3.step=0; bk[k3.num]=0; flag[k3.num]=2; q1[t1++]=k1; q2[t2++]=k3; while(h1!=t1||h2!=t2) { int len1=t1-h1; while(len1--) { k2=q1[h1++]; tmp[1]=k2.num/1000; tmp[2]=(k2.num%1000)/100; tmp[3]=(k2.num%100)/10; tmp[4]=k2.num%10; for(i=1;i<=4;i++) { now[1]=tmp[1]; now[2]=tmp[2]; now[3]=tmp[3]; now[4]=tmp[4]; now[i]=tmp[i]+1; if(now[i]==10) now[i]=1; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(flag[mt]==2) { printf("%d\n",k2.step+bk[mt]+1); return; } if(!flag[mt]) { flag[mt]=1; k1.num=mt; k1.step=k2.step+1; ak[mt]=k1.step; q1[t1++]=k1; } } for(i=1;i<=4;i++) { now[1]=tmp[1]; now[2]=tmp[2]; now[3]=tmp[3]; now[4]=tmp[4]; now[i]=tmp[i]-1; if(now[i]==0) now[i]=9; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(flag[mt]==2) { printf("%d\n",k2.step+bk[mt]+1); return; } if(!flag[mt]) { flag[mt]=1; k1.num=mt; k1.step=k2.step+1; ak[mt]=k1.step; q1[t1++]=k1; } } now[1]=tmp[2]; now[2]=tmp[1]; now[3]=tmp[3]; now[4]=tmp[4]; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(flag[mt]==2) { printf("%d\n",k2.step+bk[mt]+1); return; } if(!flag[mt]) { flag[mt]=1; k1.num=mt; k1.step=k2.step+1; ak[mt]=k1.step; q1[t1++]=k1; } now[1]=tmp[1]; now[2]=tmp[3]; now[3]=tmp[2]; now[4]=tmp[4]; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(flag[mt]==2) { printf("%d\n",k2.step+bk[mt]+1); return; } if(!flag[mt]) { flag[mt]=1; k1.num=mt; k1.step=k2.step+1; ak[mt]=k1.step; q1[t1++]=k1; } now[1]=tmp[1]; now[2]=tmp[2]; now[3]=tmp[4]; now[4]=tmp[3]; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(flag[mt]==2) { printf("%d\n",k2.step+bk[mt]+1); return; } if(!flag[mt]) { flag[mt]=1; k1.num=mt; k1.step=k2.step+1; ak[mt]=k1.step; q1[t1++]=k1; } // printf("%d %d %d 1\n",k2.num,k2.step,ak[k2.num]); // system("pause"); } int len2=t2-h2; while(len2--) { k4=q2[h2++]; tmp[1]=k4.num/1000; tmp[2]=(k4.num%1000)/100; tmp[3]=(k4.num%100)/10; tmp[4]=k4.num%10; for(i=1;i<=4;i++) { now[1]=tmp[1]; now[2]=tmp[2]; now[3]=tmp[3]; now[4]=tmp[4]; now[i]=tmp[i]+1; if(now[i]==10) now[i]=1; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(flag[mt]==1) { printf("%d\n",ak[mt]+k4.step+1); return; } if(!flag[mt]) { flag[mt]=2; k3.num=mt; k3.step=k4.step+1; bk[mt]=k3.step; q2[t2++]=k3; } } for(i=1;i<=4;i++) { now[1]=tmp[1]; now[2]=tmp[2]; now[3]=tmp[3]; now[4]=tmp[4]; now[i]=tmp[i]-1; if(now[i]==0) now[i]=9; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; // printf("%d %d\n",mt,ak[mt]); if(flag[mt]==1) { printf("%d\n",ak[mt]+k4.step+1); return; } if(!flag[mt]) { flag[mt]=2; k3.num=mt; k3.step=k4.step+1; bk[mt]=k3.step; q2[t2++]=k3; } } now[1]=tmp[2]; now[2]=tmp[1]; now[3]=tmp[3]; now[4]=tmp[4]; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(flag[mt]==1) { printf("%d\n",ak[mt]+k4.step+1); return; } if(!flag[mt]) { flag[mt]=2; k3.num=mt; k3.step=k4.step+1; bk[mt]=k3.step; q2[t2++]=k3; } now[1]=tmp[1]; now[2]=tmp[3]; now[3]=tmp[2]; now[4]=tmp[4]; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(flag[mt]==1) { printf("%d\n",ak[mt]+k4.step+1); return; } if(!flag[mt]) { flag[mt]=2; k3.num=mt; k3.step=k4.step+1; bk[mt]=k3.step; q2[t2++]=k3; } now[1]=tmp[1]; now[2]=tmp[2]; now[3]=tmp[4]; now[4]=tmp[3]; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(flag[mt]==1) { printf("%d\n",ak[mt]+k4.step+1); return; } if(!flag[mt]) { flag[mt]=2; k3.num=mt; k3.step=k4.step+1; bk[mt]=k3.step; q2[t2++]=k3; } // printf("%d %d %d 2\n",k4.num,k4.step,bk[k4.num]); // system("pause"); } } } int main() { int t,tk,ts; scanf("%d",&t); while(t--) { scanf("%d",&tk); scanf("%d",&ts); if(tk==ts) { printf("0\n"); continue; } A[1]=tk/1000; A[2]=(tk%1000)/100; A[3]=(tk%100)/10; A[4]=tk%10; B[1]=ts/1000; B[2]=(ts%1000)/100; B[3]=(ts%100)/10; B[4]=ts%10; aim=B[1]*1000+B[2]*100+B[3]*10+B[4]; bfs(); } return 0; }
附录:
为了便于才学算法的新人,贴出本人TLE的单向BFS代码(HDU上31ms)
代码:
#include<stdio.h> #include<algorithm> #include<queue> #include<string.h> using namespace std; int A[5],B[5],aim; bool flag[10000]; struct node { int num; int step; }; void bfs() { memset(flag,0,sizeof(flag)); node k1,k2; int tmp[5],i,now[5],mt; queue<node>q; k1.num=A[1]*1000+A[2]*100+A[3]*10+A[4]; flag[k1.num]=true; k1.step=0; q.push(k1); while(!q.empty()) { k2=q.front(); q.pop(); if(k2.num==aim) { printf("%d\n",k2.step); break; } tmp[1]=k2.num/1000; tmp[2]=(k2.num%1000)/100; tmp[3]=(k2.num%100)/10; tmp[4]=k2.num%10; for(i=1;i<=4;i++) { now[1]=tmp[1]; now[2]=tmp[2]; now[3]=tmp[3]; now[4]=tmp[4]; now[i]=tmp[i]+1; if(now[i]==10) now[i]=1; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(!flag[mt]) { flag[mt]=true; k1.num=mt; k1.step=k2.step+1; q.push(k1); } } for(i=1;i<=4;i++) { now[1]=tmp[1]; now[2]=tmp[2]; now[3]=tmp[3]; now[4]=tmp[4]; now[i]=tmp[i]-1; if(now[i]==0) now[i]=9; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(!flag[mt]) { flag[mt]=true; k1.num=mt; k1.step=k2.step+1; q.push(k1); } } now[1]=tmp[2]; now[2]=tmp[1]; now[3]=tmp[3]; now[4]=tmp[4]; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(!flag[mt]) { flag[mt]=true; k1.num=mt; k1.step=k2.step+1; q.push(k1); } now[1]=tmp[1]; now[2]=tmp[3]; now[3]=tmp[2]; now[4]=tmp[4]; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(!flag[mt]) { flag[mt]=true; k1.num=mt; k1.step=k2.step+1; q.push(k1); } now[1]=tmp[1]; now[2]=tmp[2]; now[3]=tmp[4]; now[4]=tmp[3]; mt=now[1]*1000+now[2]*100+now[3]*10+now[4]; if(!flag[mt]) { flag[mt]=true; k1.num=mt; k1.step=k2.step+1; q.push(k1); } } } int main() { int t,tk,ts; scanf("%d",&t); while(t--) { scanf("%d",&tk); scanf("%d",&ts); A[1]=tk/1000; A[2]=(tk%1000)/100; A[3]=(tk%100)/10; A[4]=tk%10; B[1]=ts/1000; B[2]=(ts%1000)/100; B[3]=(ts%100)/10; B[4]=ts%10; aim=B[1]*1000+B[2]*100+B[3]*10+B[4]; bfs(); } return 0; }