题意:
有n∗m的01矩阵
1表示可以放置一个英雄,0表示不能
任意两个英雄不能相邻放置
问总共有多少种方案数,mod 1e8
思路:
1.,这么小的数据可以想到dfs去写,但是看到要取模就知道尽管能剪枝,但情况还是很多,会超时。
2.对于每个位置只有放英雄和不放英雄两种状态,所以可以直接考虑二进制,用01串状态压缩。
3.取第i行的状态,st某二进制位上为1表示选某一列,为0表示不选。
4.将每一行的输入取反,并变成01串a[i]。
5.每一列的状态st,显然是不服合要求的,即左右的位置不能有士兵、只有输入是1的位置才能放士兵。
6.取第i-1行的状态,显然
是不服合要求的,即和上一行的士兵不能相邻。
7.转移方程就是
8.显然答案是:
ll ans=0; for(int i=0;i<cnt;i++) ans=(ans+dp[n][i])%mod; cout<<ans<<endl;
9.注意一下多组输入(还要开long long吧),同时要初始化两个数组,不然只能过10%。
Code:
#include<bits/stdc++.h>
#define js ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
const int mod=100000000;
int n,m;
ll dp[15][1<<12],a[15];
int main() {
js;
while(cin>>n>>m) {
memset(dp,0,sizeof(dp));
memset(a,0,sizeof(a));
for(int i=1;i<=n;++i)
for(int j=0;j<m;++j) {
int tmp; cin>>tmp;
tmp^=1;
a[i]|=(tmp<<j);
}
dp[0][0]=1; int cnt=1<<m;
for(int i=1;i<=n;++i)
for(int st=0;st<cnt;++st) {
if(st&(st>>1)||st&a[i]) continue;
for(int st1=0;st1<cnt;++st1) {
if(st&st1) continue;
dp[i][st]=(dp[i][st]+dp[i-1][st1])%mod;
}
}
ll ans=0;
for(int i=0;i<cnt;i++)ans=(ans+dp[n][i])%mod;
cout<<ans<<endl;
}
return 0;
} 
京公网安备 11010502036488号