poj3254 炮兵阵地弱化版,记数类dp

时间:2022-06-22 16:31:28
/*
dp[i][j]表示到第i行的状态j有多少放置方式
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
#define mod 100000000
int dp[][],mp[][],cur[],ans,n,m;
vector<int>v; inline int legal(int x){
if(x&(x<<))return false;
return true;
}
void init(){
v.clear();
ans=;
memset(dp,,sizeof dp);
for(int i=;i<=(<<m)-;i++)
if(legal(i)) v.push_back(i);
for(int i=;i<n;i++)
for(int j=;j<m;j++)
if(mp[i][j]==)cur[i]+=(<<(m-j-));
}
int place(int s,int k){//状态s能否放在第k行
if(s&cur[k])return false;
return true;
} int main(){
while(cin>>n>>m){
for(int i=;i<n;i++)
for(int j=;j<m;j++)
cin>>mp[i][j];
init();
for(int i=;i<v.size();i++)//先处理第0行的情况
if(place(v[i],))dp[][i]=;
for(int i=;i<n;i++)
for(int t=;t<v.size();t++){
if(place(v[t],i)){//如果状态t可以放在第i行
for(int j=;j<v.size();j++)//枚举i-1行的状态
if(!place(v[j],i-) || v[t]&v[j])continue;
else dp[i][t]=(dp[i][t]+dp[i-][j])%mod;
}
} for(int j=;j<v.size();j++)
ans=(ans+dp[n-][j])%mod;
printf("%d\n",ans); }
}