題目連接ios
BFS+篩素數打表c++
1.題目主要就是給定你兩個四位數的質數a,b,讓你計算從a變到b共最小須要多少步。要求每次只能變1位,而且變1位後仍然爲質數。算法
2.四位數的範圍是1000~9999,之間共有1000多個質數。因爲已經知道位數爲4位,因此能夠經過BFS來尋找最小步數。每次須要分別變換個位、十位、百位、千位,而且把符合要求的數放到隊列中,同時需標記這個數已經遍歷過一次,避免重複遍歷,直到找到目標數。spa
#include<iostream> #include<cstring> #include<queue> using namespace std; const int N = 1e4; int primes[N], cnt; bool st[N]; bool vis[N]; int t, a, b; struct Number{ int data; int steps; }; void get_primes(int n) { for(int i = 2; i <= n; i++) { if(!st[i]) primes[cnt++] = i; for(int j = 0; primes[j] <= n / i; j++) { st[primes[j]*i] = true; if(i % primes[j] == 0) break; } } } void bfs() { queue<Number> que; que.push({a, 0}); vis[a] = true; while(que.size()) { Number cur = que.front(); que.pop(); if(cur.data == b) { cout << cur.steps << endl; return ; } Number tmp; /*遍歷可能的個位*/ for(int i = 0; i <= 9; i++) { tmp.data = cur.data / 10 * 10 + i; if(vis[tmp.data] || st[tmp.data]) continue; tmp.steps = cur.steps + 1; que.push(tmp); vis[tmp.data] = true; } /*遍歷可能的十位*/ for(int i = 0; i <= 9; i++) { tmp.data = cur.data / 100 * 100 + i * 10 + cur.data % 10; if(vis[tmp.data] || st[tmp.data]) continue; tmp.steps = cur.steps + 1; que.push(tmp); vis[tmp.data] = true; } /*遍歷可能的百位*/ for(int i = 0; i <= 9; i++) { tmp.data = cur.data % 100 + i * 100 + cur.data / 1000 * 1000; if(vis[tmp.data] || st[tmp.data]) continue; tmp.steps = cur.steps + 1; que.push(tmp); vis[tmp.data] = true; } /*遍歷可能的千位*/ for(int i = 1; i <= 9; i++) { tmp.data = cur.data % 1000 + i * 1000; if(vis[tmp.data] || st[tmp.data]) continue; tmp.steps = cur.steps + 1; que.push(tmp); vis[tmp.data] = true; } } } int main() { get_primes(9999); cin >> t; while(t--) { memset(vis, 0, sizeof vis); cin >> a >> b; bfs(); } }
代碼中使用的線性篩素數模板來源code