【DFS】置棋问题

对着背影说爱祢 提交于 2020-02-09 18:20:25

题目描述

在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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!