欢迎访问我的Uva题解目录哦 https://blog.csdn.net/richenyunqi/article/details/81149109
题目描述
题意解析
输入正整数n,把整数 1 , 2 , 3 , … , n 1, 2, 3,…, n 1,2,3,…,n组成一个环,使得相邻两个整数之和均为素数。输出时从整数1开始逆时针排列。同一个环应恰好输出一次。 n ≤ 16 n≤16 n≤16。
算法设计
枚举1~n所有的排列显然会超时,需要在枚举过程中进行剪枝,即先判断与邻近数字之和是否为素数,如果不是素数,直接舍去当前取值。另外,由于n最大为16,邻近两数之和最大为32,可以直接写出40以内的素数表即可,不必使用筛法。
C++代码
#include <bits/stdc++.h>
using namespace std;
unordered_set<int> prime = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};//素数表
void f(int A[], int n, int index) {
if (index == n + 1) {
//边界条件
if (prime.find(A[1] + A[n]) != prime.end()) {
//A[n]+A[1]是素数
for (int i = 1; i <= n; ++i)//输出
printf("%d%s", A[i], i == n ? "" : " ");
puts("");
}
return;
}
for (int i = 1; i <= n; ++i)//遍历数字1~n
if (find(A + 1, A + index, i) == A + index && prime.find(A[index - 1] + i) != prime.end()) {
//如果数字i没取过,且与邻近数字之和是素数
A[index] = i;
f(A, n, index + 1);//继续递归
}
}
int main() {
int n, A[20];
for (int ii = 1; cin >> n; ++ii) {
printf("%sCase %d:\n", ii > 1 ? "\n" : "", ii);
iota(A, A + n + 1, 0);//将数组A值置位0~n
f(A, n, 2);
}
return 0;
}