题意:
有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;
}