首页 > 代码库 > DFS——poj1321棋盘问题

DFS——poj1321棋盘问题

一、题目回顾

题目链接:棋盘问题

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

二、解题思路
  • DFS+剪枝
  • 简单类

棋盘问题,棋子摆放的位置只能是#,且不能同行和同列。由于我采用的是按行递增的顺序来搜索的,因此不可能出现同行的情况,对于同列的情况,我设置了一个数组col[],来保存列的访问状态,对于之前访问过的列,棋子是不能再放在这一列上的。

dfs(begin, num) 代表将第k-num棵棋子放在begin行上,然后就剩下num-1棵棋子需要放在begin行下面。当然,可能存在第num棵棋子根本无法放在begin行上的情况,对于这种情况,dfs就回溯到上一个dfs调用的地方,重新开始,而如果遇到num=1,且第begin行的一些列可以放的话,就将方案数相应增加。

 

三、代码

 1 //dfs+剪枝
 2 #include <iostream>
 3 using namespace std;
 4 
 5 char pic[10][10];            //存储棋盘 
 6 int col[10];                //列的访问状态
 7 int c;                        //方案数 
 8 int n,k;
 9 
10 void dfs(int begin,int num)    //将第k-num棵棋子放在begin行上, 然后就剩下num-1棵棋子需要放在begin行下面
11 {
12     for(int j=0;j<n;j++)
13     {
14         if(pic[begin][j]==# && col[j]==0)
15         {
16             if(num==1)
17                 c++;
18             else
19             {
20                 col[j]=1;
21                 for(int h=begin+1;h<n-num+2;h++)
22                     dfs(h,num-1);
23                 col[j]=0;
24             }
25         }
26     }
27 }
28 
29 int main()
30 {
31     while((cin >> n >> k) && !(n==-1 && k==-1))
32     {
33         c=0;
34         for(int i=0;i<n;i++)
35             for(int j=0;j<n;j++)
36                 cin >> pic[i][j];
37         for(int i=0;i<n;i++)
38             col[i]=0;
39         for(int i=0;i<=n-k;i++) //一共要放k个棋子,每行至多一个,所以需要k行
40         {
41             dfs(i,k); //从第i行开始,放k个棋子.按照按行递增的顺序访问,一定不会出现同行
42         }
43         cout << c << endl;
44     }
45 }

 代码2

技术分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 const int maxn = 1e4+10;
 7 #define INF 0x3f3f3f3f
 8 char a[10][10];
 9 int n,k,cunt,m;            //cunt是放棋子的方案数,m是已放入棋盘的棋子数 
10 int book[10];                //计算一列是否已经放过棋子            
11 int to[4][2]={1,0,-1,0,0,1,0,-1};
12 bool vis[10][10];
13 bool flag;
14 
15 void dfs(int current_col)        //当前所在行数,感觉m也可以作为参数 
16 {
17     if(k == m){
18         cunt++;
19         return;
20     }
21     if(current_col>n)            //边界 
22         return;
23     for(int j=1;j<=n;j++){
24         if(book[j]==0 && a[current_col][j]==#)
25         {
26             book[j] = 1;            //判断 
27             m++;
28             dfs(current_col+1);
29             book[j] = 0;            //改回来方便下一行的判断 
30             m--;
31         }
32     }
33     dfs(current_col+1);             //到下一行 
34 }
35 int main()
36 {
37     while(cin>>n>>k && (n!=-1 || k!=-1)){
38         for(int i=1;i<=n;i++){
39             getchar();
40             for(int j=1;j<=n;j++){
41                 scanf("%c",&a[i][j]);
42             }
43         }
44         getchar();
45         memset(book,0,sizeof(book));
46         cunt = 0;
47         m = 0;
48         dfs(1);
49         printf("%d\n",cunt); 
50     }
51     return 0;
52 }
View Code

 

DFS——poj1321棋盘问题