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出题处 :http://poj.org/problem?id=1321
初做这题时候感觉有点像 N*N皇后的退化版本..因为此题不用考虑对角线的问题,细想如果单纯用N*N皇后(无对角线限制)的代码不行的,我们来举个例子? 例如
3 2
##.
…
##.
如果N*N皇后的代码答案得出0, 我们来分析下,N*N皇后问题是每一行都必须存在有皇后,而下棋这题是不需要满足每一行都存在棋子的,即棋子可以放置本行或者下一行,即一开始就存在两种状态 当前行i,下一行i+1 。【如果是状态i则当前行i枚举每一列, 当前列可放棋子’#’且与之前该列未放置棋子,则把进入下一个状态(i+1,n+1)(n为当前状态i,已放棋子的个数 )】【状态i+1行则直接进入下一个状态(i+1,n)(因为并未对i行每一列进行枚举,所以已放棋子数n自然保持当前状态i的数量】
AC代码如下:
#include <iostream>
#include <cstring>
using namespace std; // 采用了n皇后的解法,
// 区别在于n皇后每一行都必须要有, 此题不是。
//走法是可以选该行或者下一行
//QDOJ 2740
int vis[10],y,l,sum=0;
char maze[9][9];
void dfs(int jj,int y1)
{
if(jj==l)
{
sum++;
return ;
}
if(y1<y)
{
for(int i=0;i<y;i++) //本行状态
{
int t=i;
if(vis[t]==0&&maze[y1][t]=='#')
{
vis[t]=1;
dfs(jj+1,y1+1);
vis[t]=0;
}
}
dfs(jj,y1+1); //下一行状态
}
}
int main()
{
while(cin>>y>>l&&y!=-1)
{
for(int i=0;i<y;i++)
for(int j=0;j<y;j++)
cin>>maze[i][j];
memset(vis,0,sizeof(vis));
dfs(0,0);
cout<<sum<<endl;
sum=0;
}
}