HDU 4539 郑厂长系列故事——排兵布阵 <<状压dp

思路

被这道题折磨死了,只是发上来纪念一下,思路同方格取数(1),我已经疯了!

代码

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 int maze[110][15];
  4 int n,m;
  5 vector<int> all[110];
  6 int dp[110][200][200];
  7 int num[1<<10];
  8 bool check(int r,int state)
  9 {
 10     for(int i=m-1;i>=0;i--)
 11     {
 12         if(state&1)
 13         {
 14             if(maze[r][i]==0) return false;
 15             if(i<1) continue;
 16             if((state>>2)&1) return false;
 17         }
 18         state>>=1;
 19     }
 20     return true;
 21 }
 22 bool ok(int pre,int now,int f)
 23 {
 24     if(f==1)
 25     {
 26         if((pre>>1)&now||pre&(now>>1)) return false;
 27         return true;
 28     }
 29     else{
 30         if(!(pre&now)) return true;
 31         return false;
 32     }
 33 }
 34 void db()
 35 {
 36     int cnt=0;
 37     for(int i=0;i<n;i++)
 38     {
 39         all[i].clear();
 40         for(int state=0;state<1<<m;state++)
 41         {
 42             if(check(i,state)) 
 43             {
 44                 //cout<<i<<":"<<bitset<3>(state)<<endl;
 45                 cnt++,all[i].push_back(state);
 46                 num[state]=__builtin_popcount(state);
 47             }
 48         }
 49     }
 50     //cout<<cnt<<endl;
 51 }
 52 int main()
 53 {
 54     //freopen("data.in","r",stdin);
 55     //freopen("data.out","w",stdout);
 56     while(~scanf("%d%d",&n,&m))
 57     {
 58         memset(maze,0,sizeof(maze));
 59         for(int i=0;i<n;i++)
 60         {
 61             for(int j=0;j<m;j++)
 62             {
 63                 scanf("%d",&maze[i][j]);
 64             }
 65         }
 66         db();
 67         memset(dp,0,sizeof(dp));
 68         int ans=0;
 69         if(n==1)
 70         {
 71             for(int i=0;i<all[0].size();i++)
 72             {
 73                 ans=max(ans,num[all[0][i]]);
 74             }
 75             goto ending;
 76         }
 77         for(int i=0;i<all[0].size();i++)
 78         {
 79             for(int j=0;j<all[1].size();j++)
 80             {
 81                 int now=all[1][j],pre=all[0][i];
 82                 if(ok(pre,now,1))
 83                 {
 84                     dp[1][j][i]=max(num[all[1][j]]+num[all[0][i]],dp[1][j][i]);
 85                     //cout<<dp[1][j][i]<<endl;
 86                     ans=max(ans,dp[1][j][i]);
 87                 }
 88             }
 89         }
 90         for(int i=2;i<n;i++)
 91         {
 92             for(int j=0;j<all[i].size();j++)
 93             {
 94                 for(int k=0;k<all[i-1].size();k++)
 95                 {
 96                     int pre=all[i-1][k],now=all[i][j];
 97                     if(!ok(pre,now,1)) continue;
 98                     else{
 99                         for(int l=0;l<all[i-2].size();l++)
100                         {
101                             int pp=all[i-2][l];
102                             if(ok(pp,now,2)&&ok(pp,pre,1))
103                             {
104                                 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+num[all[i][j]]);
105                                 ans=max(ans,dp[i][j][k]);
106                             }
107                         }
108                     }
109                 }
110             }        
111         }
112         ending:
113         printf("%d\n",ans);
114     }
115 }

 

转载于:https://www.cnblogs.com/computer-luo/p/10074351.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值