王道机试练习——素数环
题目描述
由给定的 1 到 n 数字中,将数字依次填入环中,使得环中任意两 个相邻的数字间的和为素数。对于给定的 n,按字典序由小到大输出所有符合条 件的解(第一个数恒定为 1)。这就是有名的素数环问题。 为了解决该问题,我们可以采用回溯法枚举每一个值。当第一个数位为 1 确定时,我们尝试放入第二个数,使其和 1 的和为素数,放入后再尝试放入第三 个数,使其与第二个数的和为素数,直到所有的数全部被放入环中,且最后一个 数与 1 的和也是素数,那么这个方案即为答案,输出;若在尝试放数的过程中, 发现当前位置无论放置任何之前未被使用的数均不可能满足条件,那么我们回溯 改变其上一个数,直到产生我们所需要的答案,或者确实不再存在更多的解。
代码
#include<stdio.h>
#include<string.h>
int ans[22];
bool hash[22];
int n;
int prime[] = { 2,3,5,7,11,13,17,19,23,29,31,37,41 };
bool judge(int x) {
for (int i = 0; i < 13; i++) {
if (prime[i] == x) return true;
}
return false;
}
void check() {
if (judge(ans[1] + ans[n]) == false) return;
for (int i = 1; i <= n; i++) {
if (i != 1) printf(" ");
printf("%d", ans[i]);
}
printf("\n");
}
void DFS(int num) {
if (num > 1)
if (judge(ans[num] + ans[num - 1]) == false) return;
if (num == n) {
check();
return;
}
for (int i = 2; i <= n; i++) {
if (hash[i] == false) {
hash[i] = true;
ans[num + 1] = i;
DFS(num + 1);
hash[i] = false;
}
}
}
int main() {
int cas = 0;
while (scanf("%d", &n) != EOF) {
cas++;
for (int i = 0; i < 22; i++) hash[i] = false;
ans[1] = 1;
printf("Case%d:\n", cas);
hash[1] = true;
DFS(1);
printf("\n");
}
return 0;
}