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

时间: 2024-08-26 12:50:21

HDU 4539 郑厂长系列故事——排兵布阵 <<状压dp的相关文章

HDU 4539 郑厂长系列故事——排兵布阵 (状态压缩DP)

中文题,题意不再累赘. 思路:对于第 i 行的放士兵,影响它的只有第 i-1 行和 i-2 行,所以暴力枚举符合这三行的状态 state[i],state[j],state[k].  接下来就是二进制的巧妙应用了. 具体题解看代码注释!!! #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #include<cmath&

HDU 4539郑厂长系列故事――排兵布阵(状压DP)

HDU 4539  郑厂长系列故事――排兵布阵 基础的状压DP,首先记录先每一行可取的所哟状态(一行里互不冲突的大概160个状态), 直接套了一个4重循环居然没超时我就呵呵了 1 //#pragma comment(linker,"/STACK:102400000,102400000") 2 #include <map> 3 #include <set> 4 #include <stack> 5 #include <queue> 6 #i

HDU 4539 郑厂长系列故事——排兵布阵

http://acm.hdu.edu.cn/showproblem.php?pid=4539 郑厂长系列故事——排兵布阵 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1708    Accepted Submission(s): 620 Problem Description 郑厂长不是正厂长 也不是副厂长 他根本就不是厂长 事实上

HDU 4539 郑厂长系列故事――排兵布阵(状态压缩)

郑厂长系列故事--排兵布阵 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1954    Accepted Submission(s): 701 Problem Description 郑厂长不是正厂长 也不是副厂长 他根本就不是厂长 事实上 他是带兵打仗的团长 一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵. 根据以往的战

HDU 4539 郑厂长系列故事――排兵布阵

/* 曼哈顿距离的定义是:两个点的坐标为(x1,y1),(x2,y2),两点的曼哈顿距离为|x1-x2|+|y1-y2| 题意:题上要求是两个士兵的距离不能是曼哈顿距离为2,意思就是这个点在同一行同一列不能相间,这个点的左上,左下,右上,右下角不能有 士兵. 思路:dp+状态压缩dp[i][j][k]定义的状态为i是当前行,j为当前行的状态,k为上一行的状态类似炮兵阵地 */ #include<stdio.h> #include<string.h> #define Max(a,b)

HDU ACM 4539 郑厂长系列故事——排兵布阵-&gt;状态压缩DP

分析:dp[i][j][k]表示第i行状态为j,i-1行状态为k时的客房士兵的最大值. 曼哈顿距离是指:|x1-x2|+|y1-y2|. 当前行不仅与前一行有关,还和前两行有关,所以开数组的时候还要记录前两行的状态,所以开设三维数组. 每行可压缩为二进制集合,状态dp[i][j][k]为第i行为集合j,第i-1行为集合k,则状态方程dp[i][j][k] = max{dp[i-1][k][r]+cnt[j]  | 状态i,j,k要能够共存}(cnt[j]为j在二进制下的1的个数,即士兵数).第一

[状压dp]HDOJ4539 郑厂长系列故事——排兵布阵

中文题,题意不再赘述 对于“?”这一格,它所能攻击到的(曼哈顿距离为2的) 前方的 即“√”的四个位置 那么与此格有关的即它前方两行(即状压这两行) 首先预处理每行能满足的: i 和(i<<2)不能同时放 然后分别枚举前一行和再前一行的所有状态(每一行的状态至多只有2^10=1024个) 判断能否共存 注意mp==1处才能放,mp==0处不能放 HDOJ 4539

HDU - 4529 郑厂长系列故事――N骑士问题 (状态压缩DP)

Description 郑厂长不是正厂长 也不是副厂长 他根本就不是厂长 还是那个腾讯公司的码农 一个业余时间喜欢下棋的码农 最近,郑厂长对八皇后问题很感兴趣,拿着国际象棋研究了好几天,终于研究透了.兴奋之余,坐在棋盘前的他又开始无聊了.无意间,他看见眼前的棋盘上只摆了八个皇后,感觉空荡荡的,恰好又发现身边还有几个骑士,于是,他想把这些骑士也摆到棋盘上去,当然棋盘上的一个位置只能放一个棋子.因为受八皇后问题的影响,他希望自己把这些骑士摆上去之后,也要满足每2个骑士之间不能相互攻击. 现在郑厂长想

[AC自动机+状压dp] hdu 4534 郑厂长系列故事——新闻净化

题意:中文的题目,意思就是说有很多串,每个串都有权值,权值为999的串必须出现,-999的串必须不出现.权值在-999~999之间. 然后必须出现的串不超过8个.然后给一个全为小写目标串,问最少需要删除多少个字母才能够保证必须出现的串都出现,次数一样保证权值最大.输出次数和权值. 然后根据样例,那些必须出现的串,其实权值是0. 思路: 很明显一开始建自动机构成trie图,但是需要注意的就是mark和sum的更新.个人是把所有中间的节点的sum全部赋值成了-inf. 接着只有8个必须出现的串,所以