总时间限制: 1000ms 内存限制: 65536kB

描述

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

输入

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

输出

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

样例输入

  1. 2 1
  2. #.
  3. .#
  4. 4 4
  5. ...#
  6. ..#.
  7. .#..
  8. #...
  9. -1 -1

样例输出

  1. 2
  2. 1

思路

从第0行出发, 遍历每一列, 当发现棋盘#就标记放一个棋子, 深度搜索下一行.

临界条件: 当行数row等于棋盘行数N时, 方案数自增, 然后返回上一层.

代码

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. int N, K; // N行N列矩阵, K个棋子
  5. char panel[10][10]; // 棋盘
  6. int placed[10]; // 记录一列是否被放置棋子
  7. int solutionNum; // 方案数
  8. int alreadyPlace; // 已放置到棋盘的棋子数
  9. void DFS(int row) {
  10. if( alreadyPlace == K ) { // 棋子摆完了, 方案数+1
  11. solutionNum++;
  12. return;
  13. }
  14. if( row >= N )
  15. return;
  16. /* 一列一列去遍历 */
  17. for(int j = 0; j < N; j++) {
  18. if( placed[j] == 0 && panel[row][j] == '#' ) {
  19. placed[j] = 0x1; // 标记在这放棋子
  20. alreadyPlace++;
  21. DFS(row+1); // 深度搜索下一行
  22. placed[j] = 0x0; // 撤销标记
  23. alreadyPlace--;
  24. }
  25. }
  26. DFS(row+1); // 深度搜索下一行
  27. }
  28. int main() {
  29. /* Read data */
  30. while( cin >> N >> K ) {
  31. if( N == -1 || K == -1 )
  32. break;
  33. for(int i = 0; i < N; i++) {
  34. for(int j = 0; j < N; j++) {
  35. cin >> panel[i][j];
  36. }
  37. }
  38. /* Initialize data */
  39. memset(placed, 0x0, sizeof(placed));
  40. solutionNum = 0;
  41. alreadyPlace = 0;
  42. /* DFS and display result */
  43. DFS(0);
  44. cout << solutionNum << endl;
  45. }
  46. return 0;
  47. }