- 描述
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。 - 输入
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。 - 输出
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。 - 样例输入
2 1
#.
.#
4 4
…#
…#.
.#…
#…
-1 -1
- 样例输出
2
1
- 思路
深度优先搜索,从第一行遍历至最后一行。判断是否满足输入的要求。对于每一个有效棋盘位置有放置与不放置两种选择。 - 代码(c++)
#include<bits/stdc++.h>
using namespace std;
int n , k ;
char a[9][9] ;//储存输入数据
int tmp[9][9] ;//标记有效棋盘 -1为无效位置 0为有效位置未摆放棋子 1摆放棋子
int ans = 0 ;
void dfs(int N , int K ){//从第N行开始 摆K个棋
if( K == 0 ){//临界条件
ans ++ ;
return ;
}
if(N == n){//临界条件
if(K != 1 ) return ; //到最后一行时K大于一显然不符合
for(int i = 1 ; i <= n ; i++){//对于最后一行每个能摆放的位置都是一种解法
if(tmp[n][i] == 0 ){
ans++ ;
}
}
return ;
}
for(int i = 1 ; i <= n ; i++){//这一行摆琪
if(tmp[N][i] == 0 ){
for(int j = 1 ; j <= n ; j++ ){
if(tmp[j][i] == 0 ) tmp[j][i] = 1 ;
}
dfs(N+1,K-1) ;
for(int j = 1 ; j <= n ; j++ ){
if(tmp[j][i] == 1 ) tmp[j][i] = 0 ;
}
}
}
//这一行不摆棋子
dfs(N+1,K) ;
}
int main(){
while(1){
cin >> n >> k ;
if(n == -1 && k == -1 ) break ;
memset(tmp,-1,sizeof(tmp)) ;
ans = 0 ;
for(int i = 1 ; i <= n ; i ++){//输入
for(int j = 1 ; j <= n ; j++){
cin >> a[i][j] ;
if(a[i][j] == '#') tmp[i][j] = 0 ;
}
}
dfs(1,k);
cout << ans << endl ;
}
return 0 ;
}
8.OJ
http://noi.openjudge.cn/ch0205/323/