题目地址:POJ 1321
题目大意:在一个n*n大小的矩阵里,有不规则棋盘,根据描述的棋盘放入k个棋子,要求每一行,每一列只能出现一个棋子,求一共有多少种可能性
题目分析:刚看到这道题的时候,感觉就是简化版的八皇后问题啊,而且数据不大,k<=n<=8,采用回溯算法实现。不同之处有两点,一是,这道题不用检查是否存在斜线上的冲突,二是,这道题由于棋盘的不规则,所以可能在某一行一个棋子都不会有,此时应继续搜索下一列
附AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int n,k;
char a[9][9];
int total;
int k1;//当前已放置的棋子个数
bool col[9];//记录某一列是否被使用
void dfs(int cur)
{
if(k1==k){
total++;
return;
}
if(cur>=n)
return;
for(int i=0;i<n;i++)
{
if(a[cur][i]=='#'&&!col[i])
{
col[i]=true; k1++;
dfs(cur+1);
col[i]=false;k1--;
}
}
dfs(cur+1);//此行没有合适位置,继续搜索下一行
}
int main()
{
while(cin>>n>>k&&n!=-1&&k!=-1)
{
total=0;k1=0;
for(int i=0;i<n;i++)
cin>>a[i];
memset(col,false,sizeof(col));
dfs(0);
cout<<total<<endl;
}
return 0;
}
附八皇后问题两种解法代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int total;
//法一
int C[8];//每一行的占有的列状态
void dfs(int cur)
{
if(cur==8){//边界条件:说明已经成功放了8行
total++;
return;
}
for(int i=0;i<8;i++)//列
{
int ok = 1;
C[cur]=i;
for(int j=0;j<cur;j++)//判断列和斜线是否冲突
if(C[j]==C[cur]||cur-C[cur]==j-C[j]||cur+C[cur]==j+C[j]){//主斜线x-y相等,副斜线x+y相等
ok=0;break;
}
if(ok==1)
dfs(cur+1);
}
}
//法二
int vis[3][100];
void dfs1(int cur)
{
if(cur==8){
total++;
return;
}
for(int i=0;i<8;i++)
{
if(!vis[0][i]&&!vis[1][cur-i+8]&&!vis[2][cur+i])//直接判断每一个位置的列和主副对角线是否重复
{
vis[0][i]=vis[1][cur-i+8]=vis[2][cur+i]=1;
dfs1(cur+1);
vis[0][i]=vis[1][cur-i+8]=vis[2][cur+i]=0;//若回溯回来,得恢复原来的情况
}
}
}
int main()
{
total=0;
dfs(0);
cout<<total<<endl;
total=0;
dfs1(0);
cout<<total<<endl;
return 0;
}