题目链接:http://poj.org/problem?id=3126
题意:
给你两个4位数N和M,且这两个数都是素数,问N最少经过多少次变换可以变为M,变换规则是:每次只允许变化个、十、百、千位中的一位,且变换后还是一个素数.
思路:
以N为根节点,把所有N经过一次变换可以得到的数作为其子节点,再以其第一个子节点为根,依次迭代,构造出一颗解答树,然后求的是最少的变化,所以直接BFS搜索解答树,搜到的第一个答案就是满足题意的最少变换了.
代码:
1 #include <iostream> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <stack> 7 #include <queue> 8 #include <vector> 9 #include <algorithm> 10 #include <string> 11 12 typedef long long LL; 13 typedef unsigned long long ULL; 14 using namespace std; 15 const int MAXN = 10000; 16 int isprime[MAXN + 3];//isprime[i] = 1表示 i 是素数 17 int prime[MAXN], cnt = 0; 18 19 void getprime() {//预处理素数 20 memset(isprime, 0, sizeof(isprime)); 21 for(int i = 2; i <= MAXN; i++) { 22 if(!isprime[i]) prime[++cnt] = i; 23 for(int j = 1; j <= cnt && i * prime[j] <= MAXN; j++) { 24 isprime[i * prime[j]] = 1; 25 if(i % prime[j] == 0)break; 26 } 27 } 28 for(int i = 2; i <= MAXN; i++) 29 isprime[i] = !isprime[i]; 30 } 31 32 int n, k, ans; 33 int visit[MAXN + 3], step[MAXN + 3];//visit[]用于标记已经通过变换得到过的数 step[i]代表 变换到 i 需要的变换次数 34 void BFS(int st) {//从根节点开始搜索 35 memset(visit, 0, sizeof(visit)); 36 memset(step, -1, sizeof(step)); 37 queue<int> Qu; 38 Qu.push(st); 39 visit[st] = 1, step[st] = 0; 40 while(!Qu.empty()) { 41 int now = Qu.front(); 42 Qu.pop(); 43 if(now == k) {//找到答案 44 ans = step[now]; 45 return; 46 } 47 int a = now / 1000, b = now / 100 % 10, c = now / 10 % 10, d = now % 10;//分离出千、百、十、个位 48 for(int i = 1; i <= 9; i++) {//对千位进行变换 49 if(i == a) continue; 50 int nex = i * 1000 + b * 100 + c * 10 + d; 51 if(!visit[nex] && isprime[nex]) {//变换后的数未被访问过 且是素数 52 Qu.push(nex); 53 visit[nex] = 1, step[nex] = step[now] + 1; 54 } 55 } 56 for(int i = 0; i <= 9; i++) {//对百位进行变换 57 if(i == b) continue; 58 int nex = a * 1000 + i * 100 + c * 10 + d; 59 if(!visit[nex] && isprime[nex]) { 60 Qu.push(nex); 61 visit[nex] = 1, step[nex] = step[now] + 1; 62 } 63 } 64 for(int i = 0; i <= 9; i++) {//对十位进行变换 65 if(i == c) continue; 66 int nex = a * 1000 + b * 100 + i * 10 + d; 67 if(!visit[nex] && isprime[nex]) { 68 Qu.push(nex); 69 visit[nex] = 1, step[nex] = step[now] + 1; 70 } 71 } 72 for(int i = 0; i <= 9; i++) {//对个位进行变换 73 if(i == d) continue; 74 int nex = a * 1000 + b * 100 + c * 10 + i; 75 if(!visit[nex] && isprime[nex]) { 76 Qu.push(nex); 77 visit[nex] = 1, step[nex] = step[now] + 1; 78 } 79 } 80 } 81 } 82 83 int main() { 84 getprime(); 85 int T; 86 scanf("%d", &T); 87 while(T--) { 88 scanf("%d%d", &n, &k); 89 ans = -1; 90 BFS(n); 91 ans >= 0 ? printf("%d ", ans) : printf("Impossible "); 92 } 93 return 0; 94 }