一道经典的dfs,然而我找bug找了五个小时(发现很多问题,写在注释里)最后发现超时了。。。我真是。。。但是还是能反映很多问题的。
先放我超时的代码(又臭又长)
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int n;
int z=0,sum=-1; //z第几个方案
int a[25],flag[25]; //a里面存放可能数字,其实这里不用开数组,刚开始想多了,用变量就行。flag表示是否访问过
struct point
{
int x[25];
}answer[10000]; //由于最后要按最小字典序输出,所以定义结构体,每个结构体里面放一种可能顺序
bool sushuceshi(int n1)
{
if(n1==2)return true;
if((n1&1)==0)return false;
for(int i=3;i*i<=n1;i+=2)
if(n1%i==0)return false;
return true;
}
int dfs(int xh,int d,int z)
{
if(!sushuceshi(a[xh]+answer[z].x[d-1]))return 0;
if(d==n-1)
{
if(sushuceshi(a[xh]+1))
{if(z>sum)sum=z; //为了使方案数能都叠加
answer[z].x[d]=a[xh];flag[xh]=0;return 1;}
else return 0;
}
flag[xh]=1;
answer[z].x[d]=a[xh];
int flag1=0;
for(int i=0;i<n;i++)
if(flag[i]==0)
if(dfs(i,d+1,z)!=0)
{flag1++; //不可以直接return,有多种可能比如说123或者124如果选择3就return那么4就没选到。下面的z表示提供新的方案
z++;
for(int e=0;e<=d;e++)
answer[z].x[e]=answer[z-1].x[e]; //给新的方案前面的数赋值,这里注意要赋初值啊,没有给e赋初值找了几个小时的bug
flag[i]=0;} //新的方案,所以123中的3要变回没被访问过
if(flag1!=0)return 1;
flag[xh]=0; //选择一个数但后面的数都不可以比如说选择2然后123不可以124不可以12。。都不行那么2就不行
return 0;
}
bool cmp(const point&a,const point&c) //字典序
{
for(int i=0;i<n;i++)
{
if(a.x[i]<c.x[i])return true;
else if(a.x[i]>c.x[i])return false;
}
return true;
}
int main()
{
while(cin>>n)
{
z=0;
memset(flag,0,sizeof(flag));
for(int i=0;i<n;i++)a[i]=i+1;
answer[0].x[0]=1;
flag[0]=1;
int d=0;
for(int i=1;i<n;i++)
if(dfs(i,d+1,z)!=0)
{
z=sum+1; //更新x值
answer[z].x[0]=1;
memset(flag,0,sizeof(flag));
flag[0]=1;}
sort(answer,answer+z,cmp);
for(int i=0;i<z;i++)
{
for(int w=0;w<n;w++)
cout<<answer[i].x[w]<<" ";
cout<<endl;
}
}
}
总的来说,思路就是,首先每个方案第一个值都为1然后dfs输入选择的数字(a数组中数字的下标)还有次序(在环里面是第几个)
如果前面一个和当下这个数字和为素数那么就标记访问,标记次序数组(answer【z】。x【d】)的值,然后再去选择下一个(for循环)。
每次选择完下一个返回时记得增加z(方案数)的值,并且将原来对下一个选择的操作全部清空,在选择新的看看有没有新的方案(保证可以出现1 2 3 8 5 6 7 4和1 2 5 8 3 4 7 6两种方案都在)
输出时不用考虑顺时针或逆时针,dfs在搜索时本来就找到了。
样例过了,但是T了,其实这里面有一个问题就是你不知道有多少个方案,也就是answer你不知道开多少组。
看了一下题解。发现自己真是个睿智。搜索本来就是最小字典序了,所以不需要结构体。把代码相应结构体删了之后再改了一下。发上去pe再看了一下有几个注意点:
1.每一个case都要空行!
2.每一组方案最后不要空格直接换行(跳过一个坑没想到这里居然没看到)
然后ac了,以下代码
#include<iostream>//(16.07)
#include<string.h>
using namespace std;
int n;
int a[25],flag[25];
int sum=0,i=1;
bool sushuceshi(int n1)
{
if(n1==2)return true;
if((n1&1)==0)return false;
for(int i=3;i*i<=n1;i+=2)
if(n1%i==0)return false;
return true;
}
void dfs(int sz,int d)
{
if(!sushuceshi(sz+a[d-1]))return;
if(d==n-1)
{
if(sushuceshi(sz+1))
{a[d]=sz;flag[sz]=0;
for(int e=0;e<=d;e++)
{cout<<a[e];
if(e!=d)cout<<" ";}
cout<<endl;sum++;
}
}
flag[sz]=1;
a[d]=sz;
for(int i=1;i<=n;i++)
if(flag[i]==0){dfs(i,d+1);flag[i]=0;}
}
int main()
{
while(cin>>n)
{
cout<<"Case "<<i<<":"<<endl;i++;
memset(flag,0,sizeof(flag));
flag[1]=1;
if(n==1)cout<<"1"<<endl;
for(int i=2;i<=n;i++)
{a[0]=1;dfs(i,1);flag[i]=0;}
cout<<endl;
}
}