欢迎指正!
先放几个相关链接:
2. poj1321 题目链接
3. zoj1002 题目链接
4. 八皇后问题
八皇后问题通常被当作回溯法的典型案列。【回溯法】,其实换一个通俗易懂的名字,其实就是<递归枚举>,再说得通俗一点,其实就是一种<暴力>。 因此,这种解法时间耗费其实是指数级增长。基于此,题目中的N(递归树、解答树层数?)一般不会给太大。
知乎上有这样一个有个话题,叫《如何用十行代码搞定八皇后》。刘汝佳那本算法书上就是十行搞定的。哇,感觉这么经典的十行代码,不把它记在心里真是有点可惜了:
void search(int cur){
if(cur==n) ans++;
else
for(int i=0;i<n;i++){
int ok=1;
C[cur]=i;//尝试把cur行的皇后放在第i列
for(int j=0;j<cur;j++)
if(C[cur]==C[j]||cur-C[cur]==j-C[j]||cur+C[cur]==j+C[j]){
ok=0;break;
}
if(ok) search(cur+1);
}
}
zoj1002代码:
【ps:这道题由于求得是碉堡最多可以放置多少个,这就让我一开始尝试用贪心法去解答。但是结果案例四会出错,细想一下,发现这条路走不通(打补丁都补不住)】
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n;
int ans;
char mmap[4][4];
int isOK(int x,int y)
{
int caution=0;
for(int j=0; j<y; j++)
{
if(mmap[x][j]=='*')
caution=1;
if(mmap[x][j]=='X')
caution=0;
}
if(caution)
return 0;
else
{
for(int i=0; i<x; i++)
{
if(mmap[i][y]=='*')
caution=1;
if(mmap[i][y]=='X')
caution=0;
}
if(caution)
return 0;
else
return 1;
}
}
//将所有的位置从0到n*n-1标号。当前位置为k,当前已经摆放m个碉堡
void dfs(int k,int m)
{
// cout<<"hahah "<<"k="<<k<<" m="<<m<<"\n";
if(k==n*n) //遍历完所有位置
{
// cout<<"m="<<m<<"\n";
if(m>ans)
ans=m;
return;
}
else
{
int x=k/n;
int y=k%n;
// cout<<"x="<<x<<" "<<"y="<<y<<"\n";
if(mmap[x][y]=='.'&&isOK(x,y))
{
mmap[x][y]='*';//摆上碉堡
dfs(k+1,m+1);
mmap[x][y]='.';//递归返回时一定要恢复原状
}
dfs(k+1,m);
}
}
int main()
{
while(~scanf("%d",&n)&&n!=0)
{
ans=0;
for(int i=0; i<n; i++)
scanf("%s",&mmap[i]);
dfs(0,0);
cout<<ans<<"\n";
}
return 0;
}
poj1321:
这道题做了有点时间了,不过做上面zoj1002的时候马上就想到它了。这道题比zoj1002更接近八皇后原题。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char a[10][10]; //记录棋盘位置
int book[10]; //记录一列是否已经放过棋子
int n,k;
int total,m; //total 是放棋子的方案数 ,m是已放入棋盘的棋子数目
void DFS(int cur)
{
if(k==m)
{
total++;
return ;
}
if(cur>=n) //边界
return ;
for(int j=0; j<n; j++)
if(book[j]==0 && a[cur][j]=='#') //判断条件
{
book[j]=1; //标记
m++;
DFS(cur+1);
book[j]=0; //第cur可以放 ,也可以不放,改回来的目的就是
m--; // 到29行,判断cur可以放但是不放的情况
}
DFS(cur+1); //到下一行
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&k)&&n!=-1&&k!=-1) //限制条件
{
total=0;
m=0;
for(i=0; i<n; i++)
scanf("%s",&a[i]);
memset(book,0,sizeof(book));
DFS(0);
printf("%d\n",total);
}
return 0;
}