题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1016
Problem Description A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.
Input n (0 < n < 20).
Output The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.
Sample Input 6 8
Sample Output Case 1: 1 4 3 2 5 6 1 6 5 2 3 4 Case 2: 1 2 3 8 5 6 7 4 1 2 5 8 3 4 7 6 1 4 7 6 5 8 3 2 1 6 7 4 3 8 5 2
|
题目大意:给定整数n,寻找所有的素数环,即满足从1..n共n个数,形成的环上相邻两个数之和为素数。
题解: 用普通的DFS把所有的情况搜出来即可,不过这道题可以剪下枝。
在数大于等于1而且不重复的情况下,
偶数+偶数!=素数,
奇数+奇数!=素数,
所以相邻的2个数一定是一奇一偶。
所以可以判断出当输入的数n为奇数时,一定没有满足条件的素数环,如图,比如n=5,顺时针按照奇数偶数交错放置的话,最后一个数和第一个数一定同为奇数,不满足素数和条件。
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n; // 输入
bool vis[25];
int ret[25] = {0,1};
// 判断素数
bool isPrime(int n) {
if(n == 1)
return false;
for(int i = 2;i*i <= n;i++) {
if(n % i == 0)
return false;
}
return true;
}
void dfs(int depth) {
if (depth == n) {
if(isPrime(ret[n]+1) == false)
return;
// 顺时针输出结果
for (int i = 1;i < n;i++)
printf("%d ",ret[i]);
printf("%d\n",ret[n]);
return;
}
for (int i = 2;i <= n;i++) {
if (vis[i])
continue;
// 剪枝
// if (( ret[depth]%2==0&&(i%2)==0 ) || ( ret[depth]%2!=0&&(i%2)!=0 ))
// continue;
if (isPrime(i+ret[depth]) == false)
continue;
ret[depth+1] = i;
vis[i] = true;
dfs(depth+1);
vis[i] = false;
}
}
int main(){
int Case = 1;
while(scanf("%d",&n) != EOF) {
// 初始化
memset(vis,0,sizeof(vis));
vis[1] = true;
ret[1] = 1;
printf("Case %d:\n",Case++);
if (n % 2 == 0)
dfs(1);
printf("\n");
}
return 0;
}