意思是给你一个数n,要构成一个素数环,这个素数由1-n组成,它的特征是选中环上的任意一个数字i,i与它相连的两个数加起来都分别为素数,满足就输出。
这个题的做法和hdu1015做法差不多都是使用dfs 回溯。不同之处在于这个要全部搜索,而hdu1015只需要搜索第一组就可以。
其次在这个题目中使用素数打表的方式简化素数判定,在一定情况下也是对效率有所提高的。
Prime Ring Problem
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 34615 Accepted Submission(s): 15331
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
#include <cstdio>
#include <cmath>
#include <cstring>
#define maxn 20
using namespace std;
bool dp[maxn][maxn];//记忆素数数组
int n;
bool isvisited[maxn+3];
int m[maxn+3];
void is_prime(){
for(int i=1;i<20;i++)
for(int j=1;j<20;j++){
int test=i+j;
int flag=0;
for(int x=2;x*x<=test;x++){
if(test%x==0){
dp[i][j]=false;
flag=1;
break;
}
}
if(!flag)
dp[i][j]=true;
}
}
void pt(){
int first=0;
for(int i=1;i<=n;i++){
if(first)
printf(" ");
else
first=1;
printf("%d",m[i]);
}
printf("\n");
}
void dfs(int k){
//选到最后一个了
//肯定不能忘了判定是否与第一个1加起来是素数
if(k==n&&dp[m[k]][1]){
//执行打印任务
pt();
return ;
}
for(int i=2;i<=n;i++)
//判断这个数用过没有
if(isvisited[i]==false){
if(dp[i][m[k]]){//查表,判定加和是否为素数
isvisited[i]=true;//标记使用状态
m[k+1]=i;//当前值已经可取
dfs(k+1);//向下搜索
isvisited[i]=false;//回溯
}
}
}
int main(){
int ca=1;
memset(dp,false,sizeof(dp));
is_prime();//打表
while(scanf("%d",&n)!=EOF){
printf("Case %d:\n",ca);
memset(isvisited,false,sizeof(isvisited));
m[1]=1;//题目要求第一个必须是1
dfs(1);//所以我们已经先有一个了,然后向下搜索
ca++;
printf("\n");//注意输出完毕以后还有一个空行
}
return 0;
}
今天还不错,第一个就ac,相当于lol拿首胜。。哈啊哈
版权声明:本文为博主原创文章,未经博主允许不得转载。