POJ1321 棋盘问题 —— DFS回溯

题目链接:http://poj.org/problem?id=1321


 

棋盘问题
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 50263   Accepted: 24352

 

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

Source

 



题解:

类似于八皇后问题。

由于题目要求放k个,不像八皇后那样固定了8个,所以在一开始时不知道怎样处理“k个”。即如果实际能放的位置比k要大时该怎么处理

一开始是想:在能够放的地方,执行两种操作,放和不放。但是却会出现重复,因为对于一行,不放的位置可以是多个,这就有了多种情况,但实际上这多种情况都是一样的,因为对于接下来的行,所呈现的状态是一样的。

正确的操作是:把操作对象从“一个”改为“一行”。对于每一行,有放和不放两种操作,如果不放,则直接跳过;如果放,则再决定放在哪个位置。




代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <string>
11 #include <set>
12 #define ms(a,b) memset((a),(b),sizeof((a)))
13 using namespace std;
14 typedef long long LL;
15 const int INF = 2e9;
16 const LL LNF = 9e18;
17 const int MOD = 1e9+7;
18 const int MAXN = 8+10;
19 
20 int n, k, ans;
21 char m[MAXN][MAXN];
22 int col[MAXN];
23 
24 void dfs(int dep, int t)
25 {
26     if(dep==n+1)    //到达末时,如果刚好放了k个,则计数器+1
27     {
28         if(t==k)  ans++;
29         return;
30     }
31 
32     dfs(dep+1, t);  //这一行不放
33     for(int i = 1; i<=n; i++)   //这一行放
34     {
35         if(m[dep][i]=='#' && col[i]==0 && t<k )  //t<k为剪枝
36         {
37             col[i] = 1;
38             dfs(dep+1, t+1);
39             col[i] = 0;
40         }
41     }
42 
43 //以下为错误的思想
44 //    for(int i = 1; i<=n; i++)
45 //    {
46 //        if(m[dep][i]=='#' && col[i]==0 )
47 //        {
48 //            dfs(dep+1, t);    //会出现重复
49 //            col[i] = 1;
50 //            dfs(dep+1, t+1);
51 //            col[i] = 0;
52 //        }
53 //    }
54 
55 }
56 
57 int main()
58 {
59     while(scanf("%d%d",&n,&k))
60     {
61         if(n==-1 && k==-1) break;
62 
63         ms(col,0);
64         ans = 0;
65         for(int i = 1; i<=n; i++)
66             scanf("%s", m[i]+1);
67 
68         dfs(1, 0);
69         cout<< ans <<endl;
70     }
71 }
View Code

 



 

posted on 2017-09-01 10:55  h_z_cong  阅读(196)  评论(0编辑  收藏  举报

导航