POJ1321 棋盘问题

POJ1321 棋盘问题

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放\(k\)个棋子的所有可行的摆放方案\(C\)

输入含有多组测试数据。
每组数据的第一行是两个正整数,\(n\) \(k\),用一个空格隔开,表示了将在一个\(n \times n\)的矩阵内描述棋盘,以及摆放棋子的数目。 \(n \le 8 , k \le n\)
当为\(-1 -1\)时表示输入结束。
随后的\(n\)行描述了棋盘的形状:每行有\(n\)个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。

对于每一组数据,给出一行输出,输出摆放的方案数目\(C\) (数据保证\(C<2^{31}\))。

2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1

2
1

这是一道简单的搜索题。

因为棋子是没有区别的,所以搜索不能搜每个棋子放在哪个位置,而是要搜每个位置要不要放棋子。

每次要放的时候标记一下行和列就可以了。

为什么呢?

举个例子,如果(1,1),(2,2),(3,3),(4,4)可以放棋子,要放4个。如果按照第一种搜索方法,第一次就会搜到:(1,1),(2,2),(3,3),(4,4),然后函数会回溯到第三层,然后第三个棋子又放在了(4,4),然后就搜到:(1,1),(2,2),(4,4)(3,3),就错了。而第二种方法会搜(1,1)放不放,(2,2)放不放,(3,3)放不放,(4,4)放不放,而搜到的全部的16种情况中,只有(1,1)放,(2,2)放,(3,3)放,(4,4)放这一种情况满足放4个的要求,这样就正确了。

代码

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 10;
int n, k, ans;
char str[MAXN][MAXN];
bool lie[MAXN], hang[MAXN];
void dfs(int x, int y, int cnt) {
	if(cnt == k + 1){//放够了,返回 
		ans ++;
		return ;
	}
	if(x == n + 1)//搜出去了 
		return ;
		
	y + 1 <= n ? dfs(x, y + 1, cnt) : dfs(x + 1 ,1 ,cnt);//不放
	
	if (str[x][y] == '#' && ! hang[x] && ! lie[y]) {//放 
		hang[x] = lie[y] = 1;//标记
		y + 1 <= n ? dfs(x, y + 1, cnt + 1) : dfs(x + 1 ,1 ,cnt + 1);
		hang[x] = lie[y] = 0;//标记
	} 
}
int main() {
	while (scanf("%d%d", &n, &k) != EOF) {
		if (n == -1 && k == -1) 
			break;		
		for (int i = 1; i <= n; i ++)
			scanf("%s", str[i] + 1);
		ans = 0;
		
		dfs(1, 1, 1);
	
		printf("%d\n", ans);
	}
	return 0;
}
posted @ 2023-01-13 22:47  maniubi  阅读(16)  评论(0编辑  收藏  举报