牛客比赛-状压dp

链接:https://www.nowcoder.com/acm/contest/74/F
来源:牛客网

德玛西亚是一个实力雄厚、奉公守法的国家,有着功勋卓著的光荣军史。
这里非常重视正义、荣耀、职责的意识形态,这里的人民为此感到强烈自豪。
有一天他们想去制裁邪恶的比尔吉沃特,于是派遣了自己最优秀的战士。
结果比尔吉沃特领土太小,只有长为n宽为m共计n*m块土地,其中有些土
地标记为0表示为高山峻岭或者深海湖泊,英雄们无法在其中站立,只有标
记为1的土地才能容纳一个英雄。德玛西亚的英雄们战斗时有一个特点,他
们不希望队友站在自己旁边显得很暧昧。请问最多能有多少种安排德玛西
亚英雄的方法?

输入描述:

输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 12, m <= 12 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的比尔吉沃特领土。

输出描述:

输出一个整数n代表安排应用的方法。
(答案取膜100000000)
示例1

输入

3 3
1 1 1
0 1 1
1 0 0

输出

24
比赛时想到状压dp,但没心情写了,刚才试了试1A了= =今天也算写了一题
0一定是0,1有可能是1也有可能是0,用轮廓线处理就好了,复杂度O(n*m*m*2^m)
一直没写卡在如何使最高位归零真是zz了,1xxxx,&上一个01111就好了。
最后记得注意边界处理。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 LL mod=100000000;
 5 int e[15][15];
 6 LL dp[2][(1<<12)+15];
 7 int main()
 8 {
 9     int n,m,i,j,k,p;
10     while(cin>>n>>m){
11         for(i=0;i<n;++i)
12             for(j=0;j<m;++j) cin>>e[i][j];
13         int cur=0;
14         memset(dp,0,sizeof(dp));
15         dp[0][0]=1;
16         for(i=0;i<n;++i)
17         {
18             for(j=0;j<m;++j)
19             {
20                 cur^=1;
21                 memset(dp[cur],0,sizeof(dp[cur]));
22                 for(k=0;k<(1<<m);++k)
23                 {
24                    dp[cur][(k<<1)&((1<<m)-1)]=(
25                    dp[cur][(k<<1)&((1<<m)-1)]+dp[cur^1][k]%mod)%mod;
26                    if(e[i][j]){
27                    if(j==0){
28                       if(!(k&(1<<(m-1))))
29                       dp[cur][(k<<1)&((1<<m)-1)|1]=
30                       (dp[cur][(k<<1)&((1<<m)-1)|1]+dp[cur^1][k])%mod;
31 
32                    }
33                    else{
34                       if(!(k&(1<<(m-1))))
35                       {
36                           if(!(k&1)){
37                             dp[cur][(k<<1)&((1<<m)-1)|1]=
38                       (dp[cur][(k<<1)&((1<<m)-1)|1]+dp[cur^1][k])%mod;
39                           }
40                       }
41                    }
42                    }
43                 }
44             }
45         }
46         LL ans=0;
47         for(k=0;k<(1<<m);++k)ans=(ans+dp[cur][k])%mod;
48         cout<<ans<<endl;
49     }
50     return 0;
51 }

 

posted @ 2018-01-30 22:51  *zzq  阅读(156)  评论(0编辑  收藏  举报