Prime Path
题意:
给定一个数据 t ,表示测试案例组数;
接下来 t 行,每行2个四位数 a、b,求把 a 变成 b 最少需要多少步,若不能按要求由 a 得到 b ,则输出“Impossible”;
条件:每次只能改变一位数字,且每次改变后的数必须是素数。
数据范围:
t <= 100
解题思路:
宽度优先搜索
先用素数筛法
得到 1000~9999 的所有素数并存入数组,然后每次由前一个素数求改变一位数后的下一个素数时,依次判断这些素数里面有没有符合条件的素数,若有则把它入队并记录得到这个素数所需变换的次数,直到得到素数 b 为止,若队列为空仍然没有找到,则说明不能按要求由 a 得到 b ,输出“Impossible”。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
using namespace std;
#define INF 0x3f3f3f
#define zero 1e-7
typedef long long ll;
const int N=1e4;
int prime[N], cnt;//prime数组存储1000~9999范围内的素数,cnt记录该范围内素数个数
int st[N];//记录得到素数i需要改变的次数
bool vis[N];//标记是否为素数
queue<int> q;
void getPrime() {
memset(vis, false, sizeof(vis));
vis[1]=true; cnt=0;
for(int i=2; i<N; i++) {//素数筛法
if(!vis[i]) {
for(int j=i*2; j<N; j+=i)
vis[j]=true;
}
}
for(int i=1000; i<=9999; i++) {
if(!vis[i])
prime[cnt++]=i;
}
return ;
}
bool judge(int a, int b) {//判断素数b是否符合条件
int num=0;
while(a && b) {
if(a%10 != b%10) num++;
a/=10; b/=10;
}
if(num==1) return true;
else return false;
}
void bfs(int from, int to) {//宽度优先搜素
while(!q.empty()) {
int top=q.front();
q.pop();
if(top==to) {
printf("%d\n", st[to]);
return ;
}
for(int i=0; i<cnt; i++) {
if(st[prime[i]]==0 && judge(top, prime[i])) {
q.push(prime[i]);
st[prime[i]]=st[top]+1;//得到prime[i]经过的步骤为得到top的步骤数+1
//printf("prime[%d]=%d, ", i, prime[i]);
}
}
}
printf("Impossible\n");
return ;
}
int main() {
int n, a, b;
getPrime();
scanf("%d", &n);
while(n--) {
memset(st, 0, sizeof(st));
while(!q.empty()) q.pop();//把队列清零
scanf("%d %d", &a, &b);
q.push(a);
bfs(a, b);
}
return 0;
}