题目链接: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个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
每组数据的第一行是两个正整数,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要大时该怎么处理
一开始是想:在能够放的地方,执行两种操作,放和不放。但是却会出现重复,因为对于一行,不放的位置可以是多个,这就有了多种情况,但实际上这多种情况都是一样的,因为对于接下来的行,所呈现的状态是一样的。
正确的操作是:把操作对象从“一个”改为“一行”。对于每一行,有放和不放两种操作,如果不放,则直接跳过;如果放,则再决定放在哪个位置。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }