原题链接:Prime Path
思路:
1.线性筛,定义数组用于记录初始状态到达目前状态的最小改变次数
2.使用BFS进行最短路搜索:
将某一位的数变为0~9中的一个数据,得到的新数num需要满足的条件:
1.1000 <= num <= 999
2.新数num是素数
3.这个数是第一次得到的
C++11里有现成的to_string()和stoi()函数可以使用,作用是将数字转为字符串和字符串转为整型,但不知道为啥这两个函数在POJ里会CE于是就手写了一下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
const int N = 1e4+10;
int tot;
int p[N];
int step[N];
bool check[N];
string tostring(int n)//整型转字符串
{
string s;
int t = 1000;
for(int i = 0; i < 4; i++)
{
s += (n / t % 10) + '0';
t /= 10;
}
return s;
}
int stoint(string s)
{
int num = 0;
for(int i = 0; i < 4; i++)
{
num = num * 10 + (s[i] - '0');
}
return num;
}
void make_prime()
{
for(int i = 2; i <= 9999; i++)
{
if(!check[i]) p[tot++] = i;
for(int j = 0; j < tot && i * p[j] <= 9999; j++)
{
check[i * p[j]] = true;
if(!(i % p[j])) break;
}
}
}
int BFS(int a,int b)//求出a变为b的最小操作次数
{
queue<int> q;
q.push(a);//初始状态入队
step[a] = 0;
while(!q.empty())
{
int t = q.front();
q.pop();
if(t == b) return step[b];
for(int i = 0; i < 4; i++)//改变哪一位
{
for(int j = 0; j <= 9; j++)//改变成什么
{
string s = tostring(t);//取出的数字变为字符串类型收据
s[i] = (j + '0');//改变某一位
int num = stoint(s);//得到的新的数据
if(num < 1000 || num > 9999) continue;//越界
if(step[num] != -1) continue;//被计算过
if(check[num]) continue;//如果是合数
q.push(num);//符合条件则入队
step[num] = step[t] + 1;
}
}
}
return -1;//找不到
}
int main()
{
int T;
scanf("%d",&T);
make_prime();//筛
while(T -- )
{
int a,b;
scanf("%d%d",&a,&b);
memset(step,-1,sizeof step);
int flag = BFS(a,b);
if(flag == -1)
printf("Impossible\n");
else
printf("%d\n",flag);
}
return 0;
}