题目描述
在M*N的主格中任意指定X个格子构成一个棋盘,而其它格子是残缺的,不能放棋子。在任一个构成的棋盘上放置K个棋子,要求任意两个棋子不得位于同一行或同一列上。求满足条件的所有方案数。
注意:棋盘是稀疏的,即X<(M*N)/2
输入:
第1行:2个整数M,N,表示棋盘的行数和列数( 1<M,N<10)
接下来是M行,每行N个空格分开的数字(0或者1),1表示相应的格子在棋盘上,0表示相应的格子不在棋盘上。
输出:
第1行:1个整数表示可放置的最多的棋子数P 接下来P行,每行分别列出放i(1≤i≤P)个棋子时的方案总数。
样例输入1:
5 4
0 1 1 1
0 1 0 0
1 1 1 0
0 0 1 0
0 0 1 1
样例输出1:
4
1:10
2:28
3:24
4:5
思路:
题目中提到两个棋子不能同行或者同列,基本可以判定为8皇后的问题了,而且还稍稍简单一些,没有对角线的问题。dfs函数两个参数,一个是行,一个是当前置了几个棋子了,行数超过棋盘行数就是停止条件。稍微不同的地方是答案的记录方式,这里用一个数组来记录, ans[step]++; 即step个棋子的方法数自增。
代码的框架也可以确定了,按行搜索,每行按列标记。
代码
#include <bits/stdc++.h>
using namespace std;
int n,m;
int mp[15][15];
int ans[100];
bool col[15];
void dfs(int r, int step){ // step:当前落了几个棋子
if(r == m){
ans[step]++; // step个棋子的走法数+1
return;
}
for(int j = 0; j < n; j++){
if(mp[r][j] == 1 && !col[j]){ // 可以落子
col[j] = true;
dfs(r+1,step+1);
col[j] = false;
}
}
dfs(r+1,step); //各列都遍历过了,传到下一行,就该结束了
}
int main(){
cin >> m >> n;
for(int i =0 ; i<m; i++){
for(int j = 0; j < n; j++){
cin >> mp[i][j];
}
}
dfs(0,0);
int ma = -999999;
for(int i = 0; i < 100 ; i++){
if(ans[i] != 0){
ma = i;
}
}
cout << ma << endl;
for(int i = 1; i < 100 ; i++){
if(ans[i] != 0){
cout << i << ":" << ans[i] << endl;
}
}
return 0;
}
来源:CSDN
作者:行仔ovo
链接:https://blog.csdn.net/u014117943/article/details/104227382