题目
HDU - 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.
Note: the number of first circle should always be 1.
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.
You are to write a program that completes above process.
Print a blank line after each case.
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
分析
题目比较水,就是数字全排列的应用,但还需要注意以下几点:
- 输入不是输入一次,而是直到输入EOF停止;
- 尾段需要额外处理;
- 输出答案的末尾不能有空格,每个答案前都要有"Case num:",num表示第num个答案,答案输出完毕还要额外输出一个空格。
具体的解题思路可以看我代码~
代码
#include<cstdio>
#include<cmath>
#include<cstring>
const int maxn = 25;
int n;
int sum; //当前放置数字的个数
int ans[maxn]; //存放结果
int vis[maxn]; //访问数组
int num; //记录输入次数
bool isPrime(int x){ //素数判定
int i,k;
if(x==2)
return true;
if(x<2||x%2==0)
return 0;
k = sqrt(x);
for(i=3;i<=k && x%i;i+=2);
if(i>k)
return 1;
else
return 0;
}
void dfs(int r){
if(r > n){ //边界
if(sum == n){ //数字全被放置完毕
printf("%d",ans[1]); //避免尾部多一个空格
for(int i = 2;i <= n;i++){
printf(" %d",ans[i]);
}
putchar(10);
}
return;
}
for(int i = 1;i <= n;i++){ //遍历数字序列
if(vis[i])
continue;
if(r == n){ //最后一个需要特殊对待
if(isPrime(ans[r-1]+i) && isPrime(1+i)){ //不但要和前一位相比较还要和第一位相比较
ans[r] = i; //记录答案
vis[i] = 1;
sum++;
dfs(r+1);
sum--; //重置状态
vis[i] = 0;
}
} else if(isPrime(ans[r-1]+i)){ //其他的就只需要和前一位相比较
ans[r] = i;
vis[i] = 1;
sum++;
dfs(r+1);
sum--;
vis[i] = 0;
}
}
}
int main(){
while(scanf("%d",&n)!=EOF){
num++;
ans[1] = 1; //第一步一定是1
vis[1] = 1;
sum = 1;
printf("Case %d:\n",num); //注意格式
dfs(2);
putchar(10);
memset(vis,0,sizeof(vis));
}
return 0;
}