poj 1185 炮兵阵地(状态压缩dp)
2015-09-14 20:28
330 查看
Description
View Code
司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队。一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<math.h> #include<algorithm> #include<queue> #include<set> #include<bitset> #include<map> #include<vector> #include<stdlib.h> using namespace std; #define max(a,b) (a) > (b) ? (a) : (b) #define min(a,b) (a) < (b) ? (a) : (b) #define ll long long #define eps 1e-10 #define MOD 1000000007 #define N 106 #define M 16 #define inf 1e12 int n,m; char mp [M]; int cnt ;//存的是给的图的二进制状态 int stk ;//预处理不会互相攻击到的所有状态 int num ;//存stk的1的个数 int dp ;//dp[i][j][k]表示在i时的状态为j,在i-1的状态为k时的最大值 int top;//top表示有多少个stk bool ok(int x){ //判断该状态是否合法,即不存在相邻的1之间的距离小于3的 if(x&(x<<1)) return false; if(x&(x<<2)) return false; return true; } void init(){//找到所有可能的合法状态,最多60种 top=0; int total=1<<m; for(int i=0;i<total;i++){ if(ok(i)){ stk[top++]=i; } } } int count_one(int x){//数一个整型数x的二进制中1的个数(用于初始化) int ans=0; while(x){ ans+=x%2; x>>=1; } return ans; } int main() { while(scanf("%d%d",&n,&m)==2){ if(n==0 && m==0) break; init(); for(int i=0;i<n;i++){ scanf("%s",mp[i]); } for(int i=0;i<n;i++){//初始化第一行 cnt[i]=0; for(int j=0;j<m;j++){ if(mp[i][j]=='H'){ cnt[i]+=(1<<j); } } } memset(dp,-1,sizeof(dp)); for(int i=0;i<top;i++){ num[i]=count_one(stk[i]); if((stk[i]&cnt[0])==0){ dp[0][i][0]=num[i]; } } /* for(int i=0;i<top;i++){ if(stk[i]&cnt[1]) continue; for(int j=0;j<top;j++){ if(stk[j]&cnt[0]) continue; if(stk[i]&stk[j]) continue; dp[1][i][j]=max(dp[1][i][j],dp[0][j][0]+num[i]); } } *///这边是初始化第二行,不初始化也行,而且更不会写错 for(int i=1;i<n;i++){ for(int t=0;t<top;t++){ if(stk[t]&cnt[i]) continue; for(int j=0;j<top;j++){ if(stk[j]&stk[t])continue; for(int k=0;k<top;k++){ if(stk[k]&stk[t]) continue; if(dp[i-1][j][k]==-1) continue; dp[i][t][j]=max(dp[i][t][j],dp[i-1][j][k]+num[t]); } } } } int ans=0; for(int i=0;i<n;i++){ for(int j=0;j<top;j++){ for(int k=0;k<top;k++){ ans=max(ans,dp[i][j][k]); } } } printf("%d\n",ans); } return 0; }
View Code
相关文章推荐
- android HttpClient的使用
- 【Linux】VirtualBox RedHat9.0 安装注意事项
- GET 和 POST的区别? 用POST方法发送登陆请求
- Java Unit Testing - JUnit & TestNG
- 二叉树3种遍历的非递归算法
- 纹理分割(二)GLMC学习
- noip2006 明明的随机数 (模拟)
- 产生死锁的原因
- ZIP压缩算法详细分析及解压实例解释
- BZOJ 1124 [POI2008]枪战Maf 贪心+乱搞
- 偏好设置保存用户信息
- Android Studio(九):引用jar及so文件
- Android Studio(九):引用jar及so文件
- HDU 5438 Ponds(2015ACM长春网络赛+枚举删点+DFS求联通块)
- STM32点阵
- iOS设计模式 - 生成器
- 常用加密方法
- HDU 5444.Elven Postman【2015 ACM/ICPC Asia Regional Changchun Online】【二叉树建立与遍历】9月14
- 修改ubuntu终端里面那个提示符
- 剑指offer在线编程题汇总与讲解(part 1)