题目大意:给你两个4位素数A和B,让你把A经过若干次修改后变为B,每次修改只能修改A中的一个数字且修改后的数要仍为素数,且修改的过程中不能出现重复的素数。问你素数A变为素数B最少需要经过几次修改。如果不存在一系列的修改使A变为B,输出Impossible。
分析:四维BFS。我们把每一个数子对应为一个四维数组,那么问题就变为了在一个四维空间中,由起始点(素数A)到终点(素数B)的最短距离了,然后打一个4位数的素数表来作为可移动的空间。需要注意的是每个点可以在其移动方向上走不固定的步数,拿素数1033来说吧,他对应于坐标cnt[1][0][3][3],我们在搜索时,让第一维坐标在0到9的范围内进行搜索,发现其对应的9个数都不是素数,接下来搜索第二维,发现1733是素数,然后把这个数作为第一个修改数。以此类推,直至搜索结束。
实现代码如下:
#include <cstdio> #include <iostream> #include <cstring> using namespace std; int dir[8][4]={{-1,0,0,0},{1,0,0,0},{0,-1,0,0},{0,1,0,0},{0,0,-1,0},{0,0,1,0},{0,0,0,-1},{0,0,0,1}}; bool prime[10001]; int ea,eb,ec,ed; typedef struct nod { int a,b,c,d; int w; }node; void is_prime() { int i,j; memset(prime,true,sizeof(prime)); for(i=2;i<=10000;i++) for(j=i*i;j<=10000;j+=i) prime[j]=false; for(i=1;i<1000;i++) prime[i]=false; } void bfs(int a,int b,int c,int d) { node que[10005]; bool s[11][11][11][11]={0}; int cmp1=1,cmp2=1; que[cmp1].a=a; que[cmp1].b=b; que[cmp1].c=c; que[cmp1].d=d; que[cmp1].w=0; s[a][b][c][d]=1; while(cmp1<=cmp2&&!s[ea][eb][ec][ed]) { for(int i=0;i<8;i++) { node cnt=que[cmp1]; int ca=cnt.a; int cb=cnt.b; int cc=cnt.c; int cd=cnt.d; while(true) { ca+=dir[i][0]; cb+=dir[i][1]; cc+=dir[i][2]; cd+=dir[i][3]; if(ca<1||ca>9||cb<0||cb>9||cc<0||cc>9||cd<0||cd>9) break; if(prime[ca*1000+cb*100+cc*10+cd]&&!s[ca][cb][cc][cd]) { cmp2++; s[ca][cb][cc][cd]=1; que[cmp2].a=ca; que[cmp2].b=cb; que[cmp2].c=cc; que[cmp2].d=cd; que[cmp2].w=que[cmp1].w+1; continue; } } } cmp1++; } if(cmp1>cmp2) puts("Impossible"); else printf("%d\n",que[cmp2].w); } int main() { is_prime(); int start,end; int t; cin>>t; while(t--) { scanf("%d%d",&start,&end); ea=end/1000; eb=(end/100)%10; ec=(end/10)%10; ed=end%10; bfs(start/1000,(start/100)%10,(start/10)%10,start%10); } return 0; }