棋盘问题(题解)POJ1321

棋盘问题

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 63999 Accepted: 30605

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

分析:利用深度优先搜索,找到在不同行且不同列棋子的摆放可能性,关键点回溯。把其他点拿起继续搜索。

  1. #include<iostream>
  2. #include<cstring>
  3. using namespace std;
  4. bool sol[9][9];
  5. bool full[9];
  6. int n, k;
  7. int staues;
  8. //以行进行的搜索,所以只需考虑列无重复即可。
  9. void DFS(int row, int num)
  10. {
  11.     int i, j;
  12.     if (num == k)
  13.     {
  14.         staues++;
  15.         return;
  16.     }//上来需先判断是否已经成功
  17.     if (row > n)
  18.     {
  19.         return;
  20.     }
  21.     for (j = 1; j <= n; j++)
  22.     {
  23.         if (sol[row][j] && !full[j])
  24.         {
  25.             full[j] = true;
  26.             DFS(row + 1, num + 1);//行列均加1继续向下搜索
  27.             full[j] = false;//回溯将位置置为没用过
  28.         }
  29.     }
  30.     DFS(row + 1, num);//加行不加列情况
  31.     return;
  32. }
  33. int main()
  34. {
  35.     int i, j;
  36.     while (cin >> n >> k)
  37.     {
  38.         if (n == -1 && k == -1)
  39.         {
  40.             break;
  41.         }
  42.         staues = 0;
  43.         memset(sol, false, sizeof(sol));
  44.         memset(full, false, sizeof(full));
  45.         for (i = 1; i <= n; i++)
  46.         {
  47.             for (j = 1; j <= n; j++)
  48.             {
  49.                 char term;
  50.                 cin >> term;
  51.                 if (term == '#')
  52.                 {
  53.                     sol[i][j] = true;
  54.                 }
  55.             }
  56.         }
  57.         DFS(1, 0);
  58.         cout << staues << endl;
  59.     }
  60.     return 0;
  61. }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值