HDU - 1016 cxsys训练第一周&第二周
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.
Inputn (0 < n < 20).
Note: the number of first circle should always be 1.
OutputThe 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 8Sample Output
Case 1: 1 4 3 2 5 6 1 6 5 2 3 4Case 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
这题第一思路显然dfs,但是最近想了一下可以用next_permutation做,结果TLE了,究其原因,就是深搜的时候剪枝做的比较好,所以运行的时间一对比(样例是n=18),会发现dfs的解法程序在不停的输出数据,但是STL的却仅仅是在闪光标。
得结论:有的题剪枝的十分优雅(比如这题,如果1 2 判断不成立,那么第二个数放2这一大支直接剪掉了),便不能用next_permutation,有的题(比如李白打酒,一道蓝桥杯水题),便可以这样做(现在一想主要原因就是蓝桥杯这个只需要结果,而不限制时间),还有啊比如让你输出全排列,你用dfs会很慢,而next_per就相对来说快一点,各有优势吧,当不需要剪枝的时候,next_per感觉还是略占优势,毕竟内部是用swap实现的而不是深搜,但是对于有大剪枝的题,还是慎用吧!因为next_per是对每一个全排列在判断是否符合条件(即搜索树上已经到叶了,相当于完全暴力完全无剪枝)
下面上next_per的代码:(TLE)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[35];
int cnt;
int su[70];
bool isPrime[55]={0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1};//写到37
void init(int n) {for(int i = 1; i<=n; i++) {a[i]=i;}
}
bool ok(int n) {int i;for(i = 1; i<n; i++) {if(!isPrime[a[i]+a[i+1]]) return 0;}if(!isPrime[a[i]+a[1]]) return 0;return 1;
}
int main()
{int n;int iCase=0;
// prime();while(~scanf("%d",&n)) {iCase++;printf("Case %d:\n",iCase);if(n==1) {printf("1\n");}memset(a,0,sizeof(a));init(n);do{if(ok(n)) {int i;for( i = 1; i<n; i++) {printf("%d ",a[i]);}printf("%d\n",a[i]);}}while(next_permutation(a+2,a+n+1));printf("\n");}return 0 ;
}
下面是dfs的代码:(用时608ms)
#include<iostream>
#include<cstring>
using namespace std;
void dfs(int step);
bool book[25];
int a[25];
int n;
bool isPrime[38] = {0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1}; //0-37的打表
int main()
{int cnt=1;while(scanf("%d",&n)!=EOF){memset(book,0,sizeof(book));memset(a,0,sizeof(a));a[1]=1; // 别忘这个!! printf("Case %d:\n",cnt);cnt++; dfs(2);printf("\n"); }return 0 ;
}
void dfs(int step){if(step==n+1&&isPrime[a[step-1]+1]){for(int i=1;i<=n;i++){printf("%d",a[i]);if(i<n){printf(" "); }else{printf("\n");}}return ;}for(int i=2;i<=n;i++){if(book[i]) continue;if(!isPrime[i+a[step-1]]) continue;book[i]=1;a[step]=i;dfs(step+1);book[i]=0;}
}