POJ百炼——1321棋盘问题
1321:棋盘问题
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
- 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
- 输入
- 输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。 - 输出
- 对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
- 样例输入
-
2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1
- 样例输出
-
2 1
- 来源
- 蔡错@pku
此题是类似于n皇后的搜索+回溯问题,可以从这一题中体会基本的搜索思想。
代码及注释如下:
#include<iostream> #include<map> #include<string> #include<cmath> #include<iomanip> #include<algorithm> #include<memory.h> //类似于n皇后问题,搜索+回溯 using namespace std; int n, K; int m[10][10]; int sum = 0;//情况总数 int visit[10];//记录列是否被访问到 int num;//num代表所用的棋子数目,num<=K void solve(int k)//k代表行数 { if (num == K)//棋子用光时,表示一种情况,sum++ { sum++; return; } if (k > n)//超过棋盘范围,返回 { return; } for (int j = 1; j <= n; j++)//在第k行中,由第一列向第n列搜索 { if (visit[j] == 0 && m[k][j] == 1) { visit[j] = 1; num++; solve(k+1);//进入下一行,然后回溯 num--; visit[j] = 0; } } solve(k + 1);//进入下一行 } int main() { while (cin >> n >> K) { sum = 0; num = 0; memset(m, 0, sizeof(m)); memset(visit, 0, sizeof(visit)); if (n == -1 && K == -1) { break; } char w; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { cin >> w; if (w == '#') { m[i][j] = 1; } } } solve(1); cout << sum << endl; } return 0; }
革命尚未成功,同志还需努力。

浙公网安备 33010602011771号