/*此题是一个典型的引用dfs的题细节颇多很有意思可能是博主之前刚学习完的缘故这道题若用素数打表会超时但是博主没有试高效打表法,直接用判断素数函数就好。此题思路是深搜每两个相邻的和是素数加一些边界判断想通了简单 一定要思路清楚不局限于作此题这个思路很相同*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define maxx 1000000+10
using namespace std;
int n;
int visit[21], a[21];//a环中的数字,visit访问的标记
int prime[maxx];//素数表
/*void init_prime()//简单素数打表
{
int i, j;
for(i = 2;i <= sqrt(1000002.0); ++i)
{
if(!prime[i])
for(j = i * i; j < 1000002; j += i)
prime[j] = 1;
}
j = 1;
for(i = 1;i <= 1000002; ++i)
if(!prime[i])
prime[j++] = 1;
else prime[j++] = 0;
}
*/
int is_prime(int y)//素数判断
{
int j;
for(j=2;j*j<=y;j++)
if(y%j==0)
return 0;
return 1;
}
void dfs(int x)
{
visit[a[x]] = 1;//②上一步处理此时的节点加下一个几点的和用的是a[x]+i的方法所以这里将每传入的这个节点置为1则自动向该节点的下一个节点扫描
if(x == n && is_prime(a[x]+a[1])){
for(int i = 1; i < n; i++)
printf("%d ", a[i]);
printf("%d\n", a[n]);//这一步的操作是为了不在最后一组数据后面当上空格而已
}
else{
for(int i = 1; i <= n ; i++){
if(!visit[i] && is_prime(a[x]+i)){//①首先想到的是判断前一个暑假后一个数是否为素数且不能重复将以前扫过的节点再次扫描
a[x+1] = i;//③这是通过遍历的方法进行的确定的路径所以每次遍历的i是路径中的元素因为之前遍历过的都已置为1这保证了结果的准确
dfs(x+1);//④给当前节点赋值后将该节点传值以为我们的思想永远是将接受的节点与下一个节点的和来判断是否为素数
visit[i] = 0;//⑤这一步不能忽略很重要的,若上一个节点回溯的话,那么上上一个节点就需要与上一个节点的下一个节点进行判断这一步便是将上一个节点的下一个节点置为未访问过
}
}
}
}
int main()
{
int cnt = 0;
while(scanf("%d", &n) != EOF){
memset(visit, 0, sizeof(visit));
//memset(prime, 0, sizeof(prime));//这里不能忘了
//init_prime();
printf("Case %d:\n", ++cnt);//这里一定要注意别把格式写错了
a[1] = 1;
dfs(1);
printf("\n");
}
return 0;
}
hdu1016
最新推荐文章于 2021-01-25 05:56:30 发布