在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放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搞过。(全排列暴搜参考蓝书相关代码)。
跑了922ms,在T的边缘疯狂试探。
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <cstring> using namespace std; int n,k; char mmap[10][10]; struct node { int x; int y; }nod[81]; bool vis[81]; vector<node>v; int ans=0; void dfs(int x,int cnt)//x表示选的序号 cnt表示已经用的棋子 //从vector里选出m个符合要求的位置 { if(cnt>k||(cnt+v.size()-x)<k) { return; } if(x==v.size()) { ans++; return; } //不选x dfs(x+1,cnt); //选x int i; bool flag=1; for(i=1;i<x;i++) { if(vis[i]&&i!=x&&(v[i].x==v[x].x||v[i].y==v[x].y))//判断是否同行同列 { flag=0; break; } } if(flag) { vis[x]=1; dfs(x+1,cnt+1); vis[x]=0; } } int main() { while(scanf("%d%d",&n,&k)!=EOF&&n!=-1&&k!=-1) { memset(mmap,0,sizeof(mmap)); memset(vis,0,sizeof(vis)); ans=0; int i,j; for(i=0;i<n;i++) { scanf("%s",mmap[i]); } v.clear(); node non; non.x=0; non.y=0; v.push_back(non);//为了使vector下标从1开始,放一个空的占位 for(i=0;i<n;i++) { for(j=0;j<n;j++) { if(mmap[i][j]=='#')//满足条件的格点放入vector { node temp; temp.x=i; temp.y=j; v.push_back(temp); } } } dfs(1,0);//暴搜 cout<<ans<<endl; } }