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;
}
本文来自博客园,作者:maniubi,转载请注明原文链接:https://www.cnblogs.com/maniubi/p/17050931.html,orz