title: HDU-1016
categories:
- ACM
- DFS
tags: - 素数环
- 回溯
date: 2020-02-17 18:12:58
典型的DFS数据类问题,介绍一个快速打表素数的方法
题目
素环问题
*时间限制:4000/2000 MS(Java /其他)内存限制:65536/32768 K(Java /其他)
提交总数:82346接受提交:33935
*
问题描述
圆环由n个圆组成,如图所示。将自然数1、2,…,n分别放入每个圆,并且两个相邻圆中的数字总和应为质数。
注意:第一个圆的数目应始终为1。
输入值
n(0 <n <20)。
输出量
输出格式如下所示。每一行代表环中从顺时针和逆时针1开始的一系列圆圈编号。数字顺序必须满足上述要求。按字典顺序打印解决方案。
您将编写一个完成上述过程的程序。
在每种情况下都打印空白行。
样本输入
6
8
样本输出
情况1:
1 4 3 2 5 6
1 6 5 2 3 4
情况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
算法
快速打表素数(0~n)
利用memset置0(对字节操作,不能置1的),0代表是素数,如果i是素数,则2i~ni都不是素数,只要将素数的倍数们都标记为非素数即可,需要注意的是它们的表示与我们通常的认知相反,用法:!sushu[i]
bool sushu[45]={0};
for(int i=2;i<8;i++)//此处的8=sqrt(45)+1
if(!sushu[i])
for(int j=i*i;j<45;j+=i)
sushu[j]=1;
代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
using namespace std;
int n;
int flag[21];
int b[21];
int sum;
bool sushu[45]={0};
bool judge(int a)
{
return !sushu[a];
}
void dfs2(int q)
{
if(q==1)
{
flag[1]=1;
b[1]=1;
dfs2(2);
return ;
}
if(q==n+1)
{
if(judge(b[q-1]+1))
{
sum++;
for(int k=1;k<=n;k++)
{
cout<<b[k];
if(k!=n)
cout<<" ";
}
cout<<endl;
}
}
for(int i=1;i<=n;i++)
{
if(flag[i]==0&&judge(b[q-1]+i))
{
flag[i]=1;
b[q]=i;
dfs2(q+1);
flag[i]=0;
}
}
}
int main()
{
for(int i=2;i<8;i++)
if(!sushu[i])
for(int j=i*i;j<45;j+=i)
sushu[j]=1;
int ca=1;
while(cin>>n)
{
cout<<"Case "<<ca++<<":"<<endl;
sum=0;
memset(flag,0,sizeof(flag));
dfs2(1);
//cout<<"种数"<<sum<<endl;
cout<<endl;
}
}
/*void dfs(int nn,int ln)
{
if(nn==1)
{
b[nn]=1;
flag[1]=1;
dfs(2,1);
return ;
}
if(nn==n+1)
{
if(judge(1+ln))
{ sum++;
for(int k=1;k<=n;k++)
{
cout<<b[k];
if(k!=n)
cout<<" ";
}
cout<<endl;
}
return ;
}
for(int i=1;i<=n;i++)
{
if(flag[i]==0&&judge(ln+i))
{
flag[i]=1;
b[nn]=i;
dfs(nn+1,i);
flag[i]=0;
}
}
}*/
presentation error
输出的最后一个数字后面不应该有空格