F - 棋盘问题 POJ - 1321

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

思路

这题和N皇后有点相似,但还是有不同点:
N皇后还要求对角线和辅对角线都不能放,需要使用额外数组去判断对角线和辅对角线有没有放过棋子
N皇后初始化时每个位置只有一种状态,而这题初始化时每个位置有'#'和'.',

只有'#'才可以放搜索的结束条件为:已经放好的棋子数量等于k,方案数加一
当前行数等于n,因为从索引为0的行开始找,当前行数等于n,也就说明0~n-1行都遍历了

在dfs函数的最后面要加上 dfs(u + 1, cnt);
因为有可能在搜索某一行时,这一行的每个位置都是’.’,也有可能除了’.'外的其他位置所在的列都放了棋子,
如果没有上面这行代码,就有可能无法进到下一行去搜索

C++ 代码

#include<iostream>
#include <algorithm>
#include<cstring>
using namespace std;

const int N =10;
int n,k,ans;//n为棋盘的行数和列数,k为要放的棋子数量,ans为方案数,cnt为已经放了多少个棋子
char g[N][N];//存储地图
bool col[N];//记录某一列是否已经放了棋子

void dfs(int u,int cnt) {
	if(cnt == k) {//如果放了的棋子数量等于k,则添加一个方案
		ans++;
		return;
	}

	if(u == n) return;//因为从索引为0的行开始找,当u等于n,也就说明0~n-1行都遍历了

	for(int i=0; i<n; i++) {
		if(g[u][i]=='#'&&!col[i]) {
			col[i]=true;
			dfs(u+1,cnt+1);
			col[i]=false;//回溯
		}
	}
	dfs(u+1,cnt);//注意这行代码
}

int main() {
	while(cin >> n >> k) {
		if(n == -1 && k == -1) break;

		for(int i=0; i<n; i++)
			for(int j=0; j<n; j++)
				cin >> g[i][j];

		ans = 0 ;
		memset(col,false,sizeof(col));
		dfs(0,0);
		cout << ans << endl;
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值