棋盘问题
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 67775 | Accepted: 32273 |
Description
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
Sample Input
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
Sample Output
2
1
Source
问题链接POJ1321 棋盘问题
解题思路
dfs
AC的C++代码
#include<iostream>
using namespace std;
const int N=15;
char b[N][N];
int ans,k,n;
//放置第几颗棋子,从第s行开始放,标记放在第j列是否合法
void dfs(int i,int s,bool vis[])
{
if(i==k+1){//已经有k个棋子放置好了,则结果加一
ans++;
return;
} //第i个棋子可以选择放置在s行~n-k+i行的某一行,由于已经放置了i-1个棋子,
//还差k-i+1个棋子,因此至少需要k-i+1行,所以第i个棋子最多放置在第n-k+i行
for(int r=s;r<=n-k+i;r++)//考虑把第i个棋子放置在第r行上
for(int j=1;j<=n;j++)
if(b[r][j]=='#'&&!vis[j]){//第r行上只有为棋盘的列且没有放置棋子的列才可以放置
vis[j]=true;//考虑把第i个棋子放置在第r行的j列上,标记
dfs(i+1,r+1,vis);
vis[j]=false;//考虑不把第i个棋子放置在第r行的j列上,取消标记
}
}
int main()
{
while(~scanf("%d%d",&n,&k)){
if(n==-1&&k==-1)
break;
ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf(" %c",&b[i][j]);
bool vis[N]={false};
dfs(1,1,vis);
printf("%d\n",ans);
}
return 0;
}