hdu 4539 郑厂长系列故事——排兵布阵 状态压缩dp
2014-05-01 22:25
399 查看
郑厂长系列故事——排兵布阵
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1606 Accepted Submission(s): 587
Problem Description
郑厂长不是正厂长
也不是副厂长
他根本就不是厂长
事实上
他是带兵打仗的团长
一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。
Input
输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。
Output
请为每组数据计算并输出最多能安排的士兵数量,每组数据输出一行。
Sample Input
6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Sample Output
2
Source
2013腾讯编程马拉松复赛第二场(3月30日)
状态压缩dp
dp[i][j][k] 第i行状态为k,i-1行状态为j时的士兵最大值
先枚举合法状态 (每一行最多不超过169)
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int mp[105],st[12][170],num[12][170];//记录状态 还有1的数目 int Rel[12][70000][3];//记录相邻三行可能的状态 int cnt1[12],cnt2[12];//记录状态数 和相邻三行状态数 int DP[105][170][170]; void cs(int m) { int bound = (1<<m) ; int i , j; cnt1[m] = 0; for( i = 0; i < bound; ++i) if(((i<<2)&i) == 0 && ((i>>2)&i) == 0){ st[m][cnt1[m]] = i; for( j = 0 ; j < m; ++j) if(i&(1<<j)) num[m][cnt1[m]]++; cnt1[m]++; } } void cr(int m) { int a,b,c,i,j,k; cnt2[m] = 0; int bound = cnt1[m]; for( i = 0; i < bound ; ++i){ a = st[m][i]; for( j = 0 ; j < bound ; ++j){ b = st[m][j]; if((a<<1)&b || (a>>1)&b) continue; for( k = 0 ; k < bound ; ++k){ c = st[m][k]; if((c<<1)&b || (c>>1)&b || c&a) continue; Rel[m][cnt2[m]][0] = i; Rel[m][cnt2[m]][1] = j; Rel[m][cnt2[m]][2] = k; cnt2[m]++; // if(m==1) cout<<i<<" "<<j<<" "<<k<<endl; } } } } void cstate() { memset(num,0,sizeof(num)); for(int i = 1;i < 11; ++i) cs(i); } void cmr() { memset(Rel,0,sizeof(Rel)); for(int i = 1; i < 11; ++i) cr(i); } int main() { cstate(); cmr(); int n,m; int a,b,c,o,p,q,ans,k,bound; int i ,j; while(~scanf("%d%d",&n, &m)) { memset(mp,0,sizeof(mp)); memset(DP,0,sizeof(DP)); for( i = 1 ; i <= n ; ++i){ for( j = 1; j <= m ; ++j){ scanf("%d",&k); mp[i] = (mp[i]<<1)|k; } mp[i] = ~mp[i]; } mp[0] = mp[n + 1] = mp[n + 2] = ~0; bound = cnt2[m]; for(i = n; i >= 0; --i) for( j = 0 ; j < bound; ++j){ a = Rel[m][j][0]; o = st[m][a]; b = Rel[m][j][1]; p = st[m][b]; c = Rel[m][j][2]; q = st[m][c]; if(o&mp[i] || p&mp[i+1] || q&mp[i+2]) continue; DP[i][b][a] = max(DP[i][b][a],DP[i+1][c][b] + num[m][a]); } ans = 0; for(i = 0 ; i < cnt1[m]; ++i) ans = max(ans,DP[0][i][0]); printf("%d\n",ans); } return 0; }上面的做法比较耗时耗空间 http://blog.csdn.net/xingyeyongheng/article/details/21559339
上面这个博客 里面的是每一次都进行枚举 这样会省很多时间和空间
还有一种做法是将矩阵旋转,当前行就只与前行有关系,这样会更高效
相关文章推荐
- HDU 4539 郑厂长系列故事——排兵布阵 (状态压缩DP)
- hdu 4539 郑厂长系列故事——排兵布阵 状态压缩+dp;
- hdu 4539 郑厂长系列故事——排兵布阵 (状态压缩dp)
- hdu 4539 郑厂长系列故事——排兵布阵(状态压缩dp)
- hdu 4539 郑厂长系列故事——排兵布阵(状态压缩dp)
- HDU 4539 郑厂长系列故事——排兵布阵(状态压缩dp)
- hdu 4539 郑厂长系列故事——排兵布阵(状态压缩DP)
- 状态压缩(1) Hdu 4539 郑厂长系列故事——排兵布阵
- 【状态压缩DP】 HDU 4539 郑厂长系列故事——排兵布阵
- HDU 4539 郑厂长系列故事――排兵布阵_状态压缩
- HDU-4539 郑厂长系列故事——排兵布阵 状态压缩DP Or 最大团
- hdu 4539 郑厂长系列故事——排兵布阵 插头dp
- HDU 4529 郑厂长系列故事——N骑士问题(状态压缩DP)
- HDU 4529 郑厂长系列故事——N骑士问题(dp,状态压缩)
- hdu 4539 郑厂长系列故事——排兵布阵 (状态压缩dp)
- 状态压缩dp hdu 4539 郑厂长系列故事——排兵布阵
- (待解决) hdu HDU4539 郑厂长系列故事——排兵布阵 (状态压缩dp~)
- hdu 4539 郑厂长系列故事——排兵布阵 (状压DP)
- HDU-4529 郑厂长系列故事——N骑士问题 状态压缩DP
- hdu 4539 郑厂长系列故事——排兵布阵(状态压缩)