题目链接:http://poj.org/problem?id=3126
题意:给你两个四位数的素数,让你把第一个素数通过一定的操作步数变成第二个,每步操作只能改变某一位的值,改变后的数也必须是素数,且不能有前导零,如果达到目的,则输出最少的步数,如果不能输出Impossible
解析:bfs好写一点,每次拿出来队头,然后枚举第几位,然后枚举这位改变为什么,判断是否合法,加入队列,一直跑到结果或队列为空为止
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
int vis[10005];
int prime[10005];
void init()
{
memset(prime,1,sizeof(prime));
for(int i=2;i<=9999;i++)
{
if(prime[i])
{
for(int j=i*2;j<=9999;j+=i)
prime[j] = false;
}
}
}
int getv(char a[])
{
int n = 0;
for(int i=0;i<4;i++)
n = n*10+a[i]-'0';
return n;
}
int change(int i,int j,int n)
{
int a[5];
a[4] = n%10;
a[3] = (n/10)%10;
a[2] = (n/100)%10;
a[1] = n/1000;
a[i] = j;
return a[1]*1000+a[2]*100+a[3]*10+a[4];
}
int bfs(int s,int ed)
{
queue<pair<int,int> >q;
q.push(make_pair(s,0));
memset(vis,0,sizeof(vis));
vis[s] = 1;
while(!q.empty())
{
pair<int,int> now = q.front();
q.pop();
if(now.first==ed)
return now.second;
for(int i=1;i<=4;i++)
{
for(int j=0;j<10;j++)
{
if(i==1 && j==0)
continue;
int tmp = change(i,j,now.first);
if(!prime[tmp] || vis[tmp])
continue;
vis[tmp] = 1;
q.push(make_pair(tmp,now.second+1));
}
}
}
return -1;
}
int main(void)
{
init();
int t;
scanf("%d",&t);
while(t--)
{
char a[10],b[10];
scanf("%s %s",a,b);
int ans = bfs(getv(a),getv(b));
if(ans==-1)
puts("Impossible");
else
printf("%d\n",ans);
}
return 0;
}