常规DFS全排列,将前后两个元素之和是否为素数的判断放在每次进入DFS之初
#include<iostream>
#include<math.h>
using namespace std;
int n,ans[21],vis[21];
int prim[51]={0}; // 假设全是素数
void doPrim()
{
// prim[0]=prim[1]=1;
for(int i=2;i<=sqrt(50);i++)
{
if(prim[i]==1) continue;
for(int j=2;i*j<=50;j++) //i是素数,则i的倍数肯定不是素数
prim[i*j]=1;
}
}
void dfs(int x)
{
// cout<<x<<endl;
if(x>=3)
{
if(prim[ans[x-1]+ans[x-2]]!=0) return; //判断前后之和是否为素数
}
if(x==n+1)
{
if(prim[ans[n]+1]!=0) return; //判断第一个和最后一个
else{
for(int i=1;i<=n-1;i++)
cout<<ans[i]<<" ";
cout<<ans[n]<<endl;
return;
}
}
for(int i=2;i<=n;i++)
{
if(vis[i]==0)
{
ans[x]=i;
vis[i]=1;
dfs(x+1);
vis[i]=0;
}
}
}
int main(void)
{
doPrim();
int count=1;
while(cin>>n)
{
cout<<"Case "<<count++<<":"<<endl;
for(int i=1;i<=n;i++)
{
ans[i]=0;
vis[i]=0;
}
ans[1]=1;
if(n==1) cout<<"1"<<endl;
else if(n==2) cout<<"1"<<" "<<"2"<<endl;
else {
dfs(2);
}
}
}
1、素数筛选法
之前按照定义
int isPrim(int sum)
{
int flag=1;
if(sum<=2) return flag;
for(int i=2;i<n;i++)
{
if(sum%i==0)
flag=0;
}
return flag;
}
素数筛选法:先假设1到N全是素数,1不做考虑,从2开始,2是素数,则2的倍数都不是素数,将2后面2的倍数都去掉,接下来2后面第一个素数是3,再将3的倍数都去掉,以此类推
int prim[51]={0};
void doPrim()
{
// prim[0]=prim[1]=1;
for(int i=2;i<=sqrt(50);i++)
{
if(prim[i]==1) continue; //不是素数则往后
for(int j=2;i*j<=50;j++) //i是素数,则i的倍数肯定不是素数
prim[i*j]=1;
}
}
2、在此问题中发现一个新问题,开始初始化假定全是素数时,我想初始化数组为全1
int prim[51]={1};
结果发现只有第一个元素被初始化为1,其余依然为0
只有在初始化为0时该语句才起效果,否则初始化列表中不足元素全补默认值,即0