素数环(dfs&&STL做法)HDU - 1016

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了素数环(dfs&&STL做法)HDU - 1016相关的知识,希望对你有一定的参考价值。


   ​​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). 


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

68

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

    这题第一思路显然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;




以上是关于素数环(dfs&&STL做法)HDU - 1016的主要内容,如果未能解决你的问题,请参考以下文章

HDU-1016素数环

HDU 1016 Prime Ring Problem(素数环问题)

hdu 1016 dfs+素数表打表

HDU 1016Prime Ring Problem

HDU 1016(DFS_B题)解题报告

UVA524 素数环 Prime Ring Problem