题意:在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
分析:这题其实就是N皇后变形,不懂N皇后的,可以参考这篇博客
因为每一行或者每一列都只能放一个棋子,所以我们直接递归每一行,用一个数组标记每一列的访问状态,然后直接DFS就行了
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<utility>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define inf 0x3f3f3f3f
#define maxn 15
#define Clear(x) memset(x,0,sizeof(x))
#define fup(i,a,b) for(int i=a;i<b;i++)
#define rfup(i,a,b) for(int i=a;i<=b;i++)
#define fdn(i,a,b) for(int i=a;i>b;i--)
#define rfdn(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
using namespace std;
const double pi=acos(-1.0);
char maze[maxn][maxn];
int vis[maxn];/**标记第i列是否已经放置过*/
int n,k,sum;
void init()
{
Clear(maze);
Clear(vis);
sum=0;
}
void dfs(int step,int row)
{
if(step==k){
sum++;
return;
}
if(row>n) return;
for(int j=0;j<n;j++)
{
if(maze[row][j]=='#'&&!vis[j])
{
vis[j]=1;
dfs(step+1,row+1);
vis[j]=0;
}
}
dfs(step,row+1);/**注意,这一条语句的作用,可以这样理解,如果有一行(不是最后一行)
字符全部都是".",没有#,如果没有这一条语句,那么由于没有"#",所以上面的for
循环的时候,不会递归到下一行,for循环结束就回溯到上一行了,但事实上呢,这一行
的下面还有图,但是都不会再跑,所以这就是这一条语句的作用*/
}
int main()
{
while(scanf("%d%d",&n,&k)==2)
{
if(n==-1||k==-1) break;
init();
for(int i=0;i<n;i++)
scanf("%s",maze[i]);
dfs(0,0);
cout<<sum<<endl;
}
return 0;
}