DFS——poj1321棋盘问题
Posted GGBeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DFS——poj1321棋盘问题相关的知识,希望对你有一定的参考价值。
一、题目回顾
题目链接:棋盘问题
Description
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
每组数据的第一行是两个正整数,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 }
以上是关于DFS——poj1321棋盘问题的主要内容,如果未能解决你的问题,请参考以下文章