“#”可放置旗子,“.”不可放置。
DFS深搜一下就好了。题目真的很简单粗暴,为什么我一开始还想用排列组合。。
问有多少中旗子摆放的方案数目,就是旗子可以摆出多少中图形,旗子顺序随意。
从第一行顺序开始往下搜索,注意,第一个放旗子的行数之后,剩下的行数肯定要比剩下的旗子数多或者等于。
不然剩下的没地方放了,也没有搜索的必要性了。
开一个bool f[M] 来记录列的状态,false为可放置状态,true则是以上行已经有旗子放置。
记得回溯的时候把状态刷回来就ok啦~!
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define FOR(i,m,n) for( int i=m;i<n;++i)
const int M = 10;
char bord[M][M];
int n,k;
bool f[M];//列
int ans;
void dfs( int line ,int row,int tmpk)
{
if( tmpk == k )
{
ans++;
return ;
}
f[row] = true;//当前列已经放置旗子
for( int i = line+1; i<= n-k+tmpk;++i)//优化
for( int j = 0;j < n;++j)
{
if( !f[j] && bord[i][j] =='#')
{
tmpk++;
dfs(i,j,tmpk);
tmpk--;
}
}
f[row] = false;//回溯
}
int main()
{
while( scanf("%d%d",&n,&k) )
{
if( n==-1 && k==-1)break;
FOR(i,0,n)
scanf("%s",bord[i]);
ans = 0;
memset(f,false,sizeof(f));//空
int tmpk = 0;
ans = 0;
for( int i=0;i<= n-k;++i)//优化
for( int j = 0; j<n;++j)
{
if( bord[i][j] =='#' && !f[i])
{
tmpk = 1;
dfs(i,j,tmpk);
}
}
printf("%d\n",ans);
}
return 0;
}