题目链接:http://poj.org/problem?id=3126
题目大意:给定两个素数(四位数),求从第一个数变换到第二个数所需要的最小次数。
变换:每次允许变换个位/十位/百位/千位的其中一个数字。且保证变换完以后该数字仍然是素数。
解题思路:bfs搜索
每次从队首取出一个元素,向40个方向扩展(实际上只有34个方向),若满足条件,将其放入队尾。
直到找到该点,则返回此时一共走过的所有步数。
代码如下:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #define MAXN 10010 5 6 int a,b; 7 struct Prime//描述一个点(素数) 8 { 9 int x,step; 10 }; 11 Prime Queue[MAXN];//模拟队列 12 bool vis[MAXN];//标记该点是否已经走过 13 14 bool JudgePrime(int n)//判断是否为素数 15 { 16 for(int i=2;i*i<=n;i++) 17 { 18 if(n%i==0) return false; 19 } 20 return true; 21 } 22 23 int bfs() 24 { 25 memset(vis,0,sizeof(vis));//初始化 26 27 int head=0,tail=1;//队首,队尾 28 //描述队首 29 Queue[0].x=a; 30 Queue[0].step=0; 31 vis[a]=1;//标记队首已经走过 32 33 while(head<tail) 34 { 35 Prime p=Queue[head++];//从队首取出一个素数,抛弃 36 37 if(p.x==b) return p.step;//若该点符合,则返回 38 39 int p1=p.x%10;//该数的个位数字 40 int p2=(p.x/10)%10;//该数的十位数字 41 int p3=(p.x/100)%10;//该数的百位数字 42 int p4=(p.x/1000);//该数的千位数字 43 44 for(int i=1;i<=9;i+=2)//变化它的个位数字 45 { 46 int temp=1000*p4+100*p3+10*p2+i; 47 if(temp!=p.x && vis[temp]==0 && JudgePrime(temp)==1) 48 { 49 vis[temp]=1; 50 Queue[tail].x=temp; 51 Queue[tail++].step=p.step+1; 52 } 53 } 54 for(int i=0;i<=9;i++)//变化它的十位数字 55 { 56 int temp=1000*p4+100*p3+10*i+p1; 57 if(temp!=p.x && vis[temp]==0 && JudgePrime(temp)==1) 58 { 59 vis[temp]=1; 60 Queue[tail].x=temp; 61 Queue[tail++].step=p.step+1; 62 } 63 } 64 for(int i=0;i<=9;i++)//变化它的百位数字 65 { 66 int temp=1000*p4+100*i+10*p2+p1; 67 if(temp!=p.x && vis[temp]==0 && JudgePrime(temp)==1) 68 { 69 vis[temp]=1; 70 Queue[tail].x=temp; 71 Queue[tail++].step=p.step+1; 72 } 73 } 74 for(int i=1;i<=9;i++)//变化它的千位数字 75 { 76 int temp=1000*i+100*p3+10*p2+p1; 77 if(temp!=p.x && vis[temp]==0 && JudgePrime(temp)==1) 78 { 79 vis[temp]=1; 80 Queue[tail].x=temp; 81 Queue[tail++].step=p.step+1; 82 } 83 } 84 } 85 } 86 87 int main() 88 { 89 int n; 90 scanf("%d",&n); 91 while(n--) 92 { 93 scanf("%d %d",&a,&b); 94 int res=bfs(); 95 printf("%d\n",res); 96 } 97 return 0; 98 }
时间: 2024-11-12 10:26:22