问题 b: 【搜索】素数路
题目:
已知一个四位的素数,要求每次修改其中的一位,并且要保证修改的结果还是一个素数,还不能出现前导零。你要找到一个修改数最少的方案,得到我们所需要的素数。
例如把1033变到8179,这里是一个最短的方案:
1033
1733
3733
3739
3779
8779
8179
修改了6次。
输入
1行,两个四位的素数(没有前导零),表示初始数和目标数。
输出
一个数,表示最少的操作次数。如果不可能,输出“Impossible”。
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
int n,m;
int prime[20000];
int a[20000];
int visit[20000];
void getprime()
{
int cnt=0;a[1]=0;
for(int i=2;i<20000;i++)
{
if(a[i]==0)prime[cnt++]=i;
for(int j=0;j<cnt&&prime[j]*i<20000;j++)
{
a[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
struct node
{
int ori;///原来的数
int a,b,c,d;///千,百,十,个位
int sign;///改变了哪一位,防止重复改变同一位
int step;///步数
}s,t;
queue<node>q;
int bfs(int ori,int a1,int b,int c,int d)
{
getprime();///打表
q.push({ori,a1,b,c,d,0,0});
while(!q.empty())
{
t=q.front();q.pop();
visit[t.ori]=true;
if(t.ori==m) return t.step;
for(int i=0;i<=9;i++)
{
///获取每一位改变后的数字,记得减去的是t.a,t.b,t.c,t.d,不是a1,b,c,d
int change1=t.ori-t.a*1000+i*1000,change2=t.ori-t.b*100+i*100;///改变千/百位
int change3=t.ori-t.c*10+i*10,change4=t.ori-t.d+i;///改变十/个位
if(i&&t.sign!=1&&a[change1]==0&&visit[change1]==false)
{
q.push({change1,i,t.b,t.c,t.d,1,t.step+1});///注意放进去的是t.b,t.c,t.d ,而不是b,c,d debug好长时间
visit[change1]=true;
}
if(t.sign!=2&&a[change2]==0&&visit[change2]==false)
{
q.push({change2,t.a,i,t.c,t.d,2,t.step+1});
visit[change2]=true;
}
if(t.sign!=3&&a[change3]==0&&visit[change3]==false)
{
q.push({change3,t.a,t.b,i,t.d,3,t.step+1});
visit[change3]=true;
}
if(t.sign!=4&&a[change4]==0&&visit[change4]==false)
{
q.push({change4,t.a,t.b,t.c,i,4,t.step+1});
visit[change4]=true;
}
}
}
return -1;
}
int main()
{
cin>>n>>m;
int a=n/1000,b=n%1000/100,c=n%100/10,d=n%10;
int sign=bfs(n,a,b,c,d);
if(sign!=-1) cout<<sign<<endl;
else cout<<"Impossible"<<endl;
return 0;
}