题意:
输入正整数n,把整数1,2,3,....,n 组成一个环,使得相邻两个整数之间整数之和均为素数,输出时从整数1开始逆序排序。n <= 16。
题解:
枚举每种情况,每个环对应于1 ~ n 的一个排列,当排列总数高达16 != 2*10**13次。
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int is_prime(int x)
{
int i;
for (i = 2; i <= sqrt(x); i++){
if (x%i == 0){
return 0;
}
}//for
return 1;
}
int main()
{
int time = 1;
int n, isp[35], A[35];
for (int i = 2; i <= 16 * 2; i++) isp[i] = is_prime(i);
while (~scanf("%d", &n)){
for (int i = 0; i < n; i++) A[i] = i + 1;
do{
int ok = 1;
for (int i = 0; i < n; i++)
if (!isp[A[i] + A[(i + 1) % n]]){
ok = 0;
break;
}
printf("Case %d:\n", time++);
if (ok){
for (int i = 0; i < n; i++)
printf("%d ", A[i]);
printf("\n\n");
}//if
} while (next_permutation(A + 1, A + n));
}//extren while
return 0;
}
当n=12时就超时了。下面试试回溯法:
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n, isp[35], A[35];
bool vis[18];
int is_prime(int x)
{
int i;
for (i = 2; i <= sqrt(x); i++){
if (x%i == 0){
return 0;
}
}//for
return 1;
}
void dfs(int cur)
{
if (cur == n && isp[A[0] + A[n - 1]]){//递归边界
for (int i = 0; i < n; i++) printf("%d ", A[i]);
printf("\n");
}
else for (int i = 2; i <= n; i++) //尝试每个数i
if (!vis[i] && isp[i + A[cur - 1]]){
A[cur] = i;
vis[i] = true;
dfs(cur + 1);
vis[i] = false; //清除标志
}
}
int main()
{
int time = 1;
for (int i = 2; i <= 16 * 2; i++) isp[i] = is_prime(i);//生成素数表
while (~scanf("%d", &n)){
memset(vis, 0, sizeof(vis));
A[0] = 1;
printf("Case %d:\n", time++);
dfs(1);
}//extren while
return 0;
}