給定兩個四位素數 start 和 target (1000~9999)。每步可修改一位數字 (千位不能為 0),且修改後必須仍為素數。求從 start 到 target 的最少步數。若無法到達輸出 "Impossible"。多測試案例 (≤ 100)。
is_prime[] 布爾數組。next。條件:next 為素數、未訪問、千位非 0。入隊記錄步數。首次到達 target 即為答案。is_prime 也極快 (節點數 ~1000,邊數 ~4000)。#includeusing namespace std; const int MAXN = 10000; bool is_prime[MAXN]; bool vis[MAXN]; struct Node { int num, step; }; void sieve() { fill(is_prime, is_prime+MAXN, true); is_prime[0] = is_prime[1] = false; for (int i = 2; i*i < MAXN; i++) if (is_prime[i]) for (int j = i*i; j < MAXN; j += i) is_prime[j] = false; } int bfs(int start, int target) { if (start == target) return 0; memset(vis, 0, sizeof(vis)); queue q; q.push({start, 0}); vis[start] = true; while (!q.empty()) { Node cur = q.front(); q.pop(); int d[4]; int tmp = cur.num; for (int i = 3; i >= 0; i--) { d[i] = tmp % 10; tmp /= 10; } for (int pos = 0; pos < 4; pos++) { for (int dig = 0; dig <= 9; dig++) { if (dig == d[pos]) continue; if (pos == 0 && dig == 0) continue; // 千位非0 int next = 0; for (int i = 0; i < 4; i++) next = next * 10 + (i == pos ? dig : d[i]); if (is_prime[next] && !vis[next]) { if (next == target) return cur.step + 1; vis[next] = true; q.push({next, cur.step + 1}); } } } } return -1; // Impossible } int main() { sieve(); int T; scanf("%d", &T); while (T--) { int s, t; scanf("%d%d", &s, &t); int ans = bfs(s, t); if (ans == -1) puts("Impossible"); else printf("%d\n", ans); } return 0; }
pos==0 && dig==0 跳過。vis,防止重複入隊。