我太菜了。。。
发现每次写完一个题的代码就要改好久。。。
这道题由于要求花费最少的路线值,考虑到BFS在这种问题下
的便利性,因此打算使用BFS算法,那么如何考虑这道题呢?
首先将题目分解成一个一个的小问题,它们分别是求出四位数
里面的素数,判断两个数是否只相差一个数字,当然还要有个
布尔数组来判断某一个数字是否使用过,这样就能够减少不必要的
访问。
需要注意的是,每次将一个数放到队列里后,下次循环就要从
四位素数表里的最小的那一位重新开始遍历,因为会有从后往前
判断的情况,例如样例里面8779 -> 8179。
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 const int N = 10000; 7 int index = 0, prime[N]; 8 bool is_prime[N], vis[N]; 9 struct node{ 10 int x, d; 11 node(int xx, int dd){ 12 x = xx, d = dd; 13 } 14 }; 15 queue<node> q; 16 void prime_shieve(){ //埃氏素数筛 17 memset(is_prime, true, sizeof(is_prime)); 18 for(int i = 2; i <= 9999; i ++){ 19 if(is_prime[i]){ 20 prime[++ index] = i; 21 for(int j = i * 2; j <= 9999; j += i) 22 is_prime[j] = false; 23 } 24 } 25 } 26 int find(int x){ //在所有四位数里求某一个数字的vis下标 27 for(int i = 1; i <= index; i ++) 28 if(prime[i] == x) 29 return i; 30 } 31 bool check(int x, int i){ //判断两个数不同的位数,有三个相同则可以替换 32 int sum = 0; 33 if(x / 1000 == i / 1000) sum ++; 34 if(x / 100 % 10 == i / 100 % 10) sum ++; 35 if(x / 10 % 10 == i / 10 % 10) sum ++; 36 if(x % 10 == i % 10) sum ++; 37 return sum == 3; 38 } 39 int bfs(int s, int e){ 40 q.push(node(s, 0)); 41 while(!q.empty()){ 42 node now = q.front(); 43 q.pop(); 44 vis[now.x] = true; 45 if(now.x == e) 46 return now.d; 47 for(int i = find(1009); i <= index; i ++) 48 if(check(now.x, prime[i]) && !vis[prime[i]]){ 49 q.push(node(prime[i], now.d + 1)); 50 vis[prime[i]] = true; 51 } 52 } 53 return -1; 54 } 55 int main(){ 56 int start, end, t; 57 prime_shieve(); 58 cin >> t; 59 while(t --){ 60 cin >> start >> end; 61 memset(vis, 0, sizeof vis); 62 while(!q.empty()) q.pop(); 63 if(start == end) 64 cout << 0 << endl; 65 else{ 66 int ans = bfs(min(start, end), max(start, end)); 67 if(ans != -1) 68 cout << ans << endl; 69 else 70 cout << "Impossible" << endl; 71 } 72 } 73 return 0; 74 }