状态dp,dp[i][j]表示进行到第i行,前i-1行的状态是j的最优答案,j中1的个数表示放了多少个,注意对于一行,可放可不放
#include <stdio.h>
#include <vector>
#include <string.h>
#include <algorithm>
using namespace std;
int n,k;
char map[9][9];
int all;
int dp[2][(1<<8)+1];
inline int getone(int i){
int ans=0;
while(i) ans++,i-=i&(-i);
return ans;
}
int main(){
while(~scanf("%d%d",&n,&k)){
if(n==-1 && k==-1) break;
for(int i=0;i<n;i++) scanf("%s",map[i]);
memset(dp,0,sizeof(dp));
dp[0][0]=1;
all=(1<<n);
int now=0;
int ans=0;
for(int i=0;i<n;i++){
now^=1;
memset(dp[now],0,sizeof(dp[now]));
for(int j=0;j<all;j++){
if(!dp[1-now][j]) continue;
for(int r=0;r<n;r++){
if(map[i][r]=='#' && (!(j&(1<<r)))){
dp[now][j^(1<<r)]+=dp[1-now][j];
}
}
dp[now][j]+=dp[1-now][j];
}
}
for(int i=0;i<all;i++){
if(getone(i)==k) ans+=dp[now][i];
}
printf("%d\n",ans);
}
}