【题目链接】
http://poj.org/problem?id=3126
题目意思
给你两个四位数的素数,问你从其中一个转换成另一个要多少步,转换时只能转换其中一个数值,且新的数值也是素数。如果不可能输出Impossible。
解题思路
用广搜直接枚举就可以了,由于素数不多只要标记下进过队的就不会爆时间
代码部分
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define LL long long
#define inf 0x3f3f3f3
const int N = 1e5+5;
int a[4]={1000,100,10,1};
int vis[N];
int n,m;
struct node ///步数和数值
{
int step,num;
}s;
bool prime(int x) ///判断是否为素数
{
for (int i = 2; i*i <= x; i++)
{
if (x%i == 0)
return false;
}
return true;
}
int qw (int num, int i) ///返回对应为数值
{
num /= a[i];
return num%10;
}
int bfs()
{
queue <node> q;
q.push(s);
vis[s.num]=1;
node t;
while (!q.empty())
{
t = q.front();
node tt;
q.pop();
if (t.num == m)
{
break;
}
tt.step = t.step+1;
for (int i = 0; i < 4; i++) ///从高位到低位
for (int j = 0; j < 10; j++) ///枚举0到9
{
if (i == 0 && j == 0) ///最高为不能为0
continue;
if (i == 3 && j%2 == 0) ///最低位为偶数注定不是素数
continue;
tt.num = t.num - qw(t.num,i)*a[i]+j*a[i]; ///替换对应权位的数
if (prime(tt.num) && !vis[tt.num]) ///如果是素数且没进入过队列
{
q.push(tt);
vis[tt.num]=1;
}
}
}
if (t.num == m)
return t.step;
else return -1;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
memset(vis,0,sizeof(vis));
scanf("%d %d",&n,&m);
s.step = 0;
s.num = n;
int t = bfs();
if (t != -1)
cout<<t<<endl;
else cout<<"Impossible"<<endl;
}
return 0;
}