首先是最经典的n皇后问题
代码如下:
#include<iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 1000;
int n;
LL ans;
int vis[3][2*maxn];
void solve(int cur)
{
if(cur==n)
ans++;
else
{
for(int i = 0;i<n;i++)
{
if(vis[0][i]==0&&vis[1][cur+i]==0&&vis[2][n+i-cur]==0)
{
vis[0][i]=vis[1][cur+i]=vis[2][n+i-cur]=1;
solve(cur+1);
vis[0][i]=vis[1][cur+i]=vis[2][n+i-cur]=0;
}
}
}
}
int main()
{
while(scanf("%d",&n)==1)
{
ans = 0;
memset(vis,0,sizeof(vis));
solve(0);
printf("%lld\n",ans);
}
}
其中vis数组中为第i列,主对角线,副对角线有无冲突,注意在本次dfs后要将数组vis还原。
然后是例题:UVa524
#include<iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int a[20];
int vis[20];
int isprime[35];
int n;
void dfs(int cur)
{
if(cur==n)
{
if(isprime[a[n-1]+a[0]]==1)
{
for(int i = 0;i<n;i++)
{
if(i!=0) printf(" ");
printf("%d",a[i]);
}
printf("\n");
}
}
else
{
for(int i = 2;i<=n;i++)
{
if(!vis[i]&&isprime[i+a[cur-1]]==1)
{
a[cur]=i;
vis[i]=1;
dfs(cur+1);
vis[i]=0;
}
}
}
}
int main()
{
int kcase=0;
memset(isprime,0,sizeof(isprime));
isprime[2]=isprime[3]=isprime[5]=isprime[7]=isprime[11]=isprime[13]=isprime[17]=isprime[19]=1;
isprime[23]=isprime[29]=isprime[31]=1;
while(scanf("%d",&n)==1)
{
if(kcase!=0) printf("\n");
printf("Case %d:\n",++kcase);
memset(vis,0,sizeof(vis));
a[0]=1;
vis[1]=1;
dfs(1);
}
}
这道题注意点有三个:
1)注意输出格式,必须是后面有数据输入的情况下,前面的空行才会输出,所以打印的空行要在前面显示。
2)注意每个结果都是从1开始的,所以先要有a[0]=1,然后从1开始dfs。
3)注意最后一个数还要与前面的第一个数加起来判断是否为素数。
UVa129
#include<iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,L;
int cnt;
int a[100];
int dfs(int cur)
{
if(cnt==n)
{
for(int i = 0;i<cur;i++)
{
if(i==64) printf("\n");
else if(i%4==0&&i!=0) printf(" ");
printf("%c",a[i]+'A');
}
printf("\n");
printf("%d\n",cur);
return 0;
}
else
{
for(int i = 0;i<L;i++)
{
a[cur]=i;
bool ok = true;
bool equal = true;
for(int j = 1;j<=(cur+1)/2;j++)
{
equal = true;
for(int k = 0;k<j;k++)
{
if(a[cur-j-k]!=a[cur-k])
{
equal = false;
break;
}
}
if(equal == true)
{
ok = false;
break;
}
}
if(ok)
{
cnt++;
if(dfs(cur+1)==0) return 0;
}
}
}
return 1;
}
int main()
{
while(scanf("%d%d",&n,&L)==2)
{
if(n==0&&L==0)
break;
cnt=0;
dfs(0);
}
}
本题目的注意要点为:
1)当dfs找到结果时,应该剪枝,利用dfs的返回结果来判定是否剪枝值得学习
2)在进行条件判断时,只需要判断当前(cur)的位置是否满足条件即可。