POJ 1321 棋盘问题
题意:在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
分析:n代表的是棋盘的大小,不等于棋盘区域的形状。按照每一行搜索,当摆放数为k时计数加一返回,否则如果满足条件则继续搜索下一行。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <queue> 6 #include <cmath> 7 #include <stack> 8 #include <set> 9 #include <map> 10 #include <algorithm> 11 using namespace std; 12 #define ll long long 13 #define inf 0x3f3f3f3f 14 char g[10][10]; 15 bool v[10]; 16 int n,k,s; 17 void dfs(int x,int num)//到第x行之前已摆放num个 18 { 19 int i,j; 20 if(num==k) 21 { 22 s++; 23 return ; 24 } 25 if(k-num>n+1-x) return ;//剪枝,如果剩余要摆放的棋子>剩余行数,返回。x从1开始故为n-x+1 26 for(i=x;i<=n;i++)//搜索x-n行的可摆放情况 27 { 28 for(j=0;j<n;j++) 29 { 30 if(g[i][j]=='#'&&!v[j]) 31 { 32 v[j]=1; 33 dfs(i+1,num+1); 34 v[j]=0; 35 } 36 //搜索第i行下一个可摆棋子的列 37 } 38 //第i行摆棋子的情况递归搜索完,继续搜索第i行不摆棋子的情况 39 } 40 } 41 int main() 42 { 43 int i,j; 44 while(~scanf("%d %d",&n,&k)) 45 { 46 if(n==-1&&k==-1) break; 47 s=0; 48 memset(v,0,sizeof v); 49 for(i=1;i<=n;i++)//行下标从1开始,列从0开始 50 scanf("%s",g[i]); 51 dfs(1,0); 52 printf("%d\n",s); 53 } 54 return 0; 55 }