状态压缩DP POJ 1185 炮兵阵地
来源:互联网 发布:域名冲突怎么解决 编辑:程序博客网 时间:2024/04/28 23:58
【题目链接】http://poj.org/problem?id=1185
【题目大意】在平原(P)上可以布置一支炮兵部队,而在山地(H)上不能够部署炮兵部队。而且每两个炮兵之间的间隔(横纵)要大于等于 2,求最多能够摆放多少的炮兵部队。
【解题思路】经典状态压缩DP。每行炮兵的状态 i,只与i-1,和i-2行状态有关。若用0表示此处不能放,1表示能放。则根据题意可知:1、有些地方不能放置;2、每种状态中任意两个1之间的间隔要大于等于2(保证横着不互相攻击)。因为是和前两行的状态有关,所以要开个三维的数组来表示状态,当前行的状态可由前两行的状态转移而来。即如果当前行的状态符合前两行的约束条件(不和前两行的大炮互相攻击),则当前行的最大值就是上一个状态的值加上当前状态中1的个数(当前行放大炮的个数)
【状态表示】dp[i][j][k] 表示第i行的状态为第k个状态,第i-1状态为第j 个状态时的最大炮兵个数。
【状态转移方程】 dp[i][j][k] = max(dp[i][j][k], dp[i-1][z][j] + num[k]);num[k]为第k个状态中1的个数
【DP边界条件】dp[1][1][i] =num[i] 状态i能够满足第一行的硬件条件(注意:这里的i指的是第i个状态,不是一个二进制数,开一个数组保存二进制状态)
【代码实现】
#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>using namespace std;char str[110][20];int h_pos[110], p_pos[110];int n, m;int num[250];int top;int dp[110][60][60];bool ok(int x){ if(x & (x << 1)) return 0; if(x & (x << 2)) return 0; return 1;}void init(){ int tot = 1 << m; top = 0; for(int i = 0; i < tot; i ++) { if(ok(i)) p_pos[++top] = i; }}//计算一个数的二进制数中1的个数,即找每种状态中能放置炮兵的个数int count1(int x){ int cnt = 0; while(x) { //if(x & 1) cnt ++; // x >>= 1; cnt ++; x &= (x-1); } return cnt;}//判断状态x是否适合第y行,即判断第y行中‘H’的位置与炮兵的位置是否冲突bool isfit(int x, int y){ if(h_pos[y] & x) return 0; return 1;}int main(){ //输入n行m列个字符,每行仅由P和H组成 while(~scanf("%d %d", &n, &m) && n+m) { for(int i = 1; i <= n; i ++) { scanf("%s", str[i]+1); } //两个炮兵之间的间距不能小于3,筛选符合条件的 init(); //计算每行中H的个数,并用二进制的形式进行存储在数组h_pos中 for(int i = 1; i <= n; i ++) { h_pos[i] = 0; for(int j = 1; j <= m; j ++) { if(str[i][j] == 'H') h_pos[i] += (1 << (j-1)); } } // printf("%d\n", top); memset(dp, -1, sizeof(dp)); for(int i = 1; i <= top; i ++) { num[i] = count1(p_pos[i]); // printf("num[i]=%d \n", num[i]); if(isfit(p_pos[i], 1)) dp[1][1][i] = num[i]; } for(int i = 2; i <= n; i ++) { for(int k = 1; k <= top; k ++) { if(!isfit(p_pos[k], i)) continue; for(int j = 1; j <= top; j ++) { if(p_pos[j] & p_pos[k]) continue; for(int z = 1; z <= top; z ++) { if(p_pos[z] & p_pos[k]) continue; if(dp[i-1][z][j]== -1) continue; dp[i][j][k] = max(dp[i][j][k], dp[i-1][z][j] + num[k]); } } } } int ans = 0; for(int i = 1; i <= n; i ++) for(int j = 1; j <= top; j ++) for(int k = 1; k <= top; k ++) ans = max(ans, dp[i][j][k]); printf("%d\n", ans); } return 0;}
- Poj 1185 炮兵阵地 【状态压缩dp】
- poj 1185 炮兵阵地 //状态压缩DP
- POJ 1185 炮兵阵地 状态压缩(DP)
- POJ 1185 炮兵阵地 状态压缩DP
- POJ 炮兵阵地 1185 状态压缩dp
- poj 1185 炮兵阵地 状态压缩dp
- poj 1185 炮兵阵地 状态压缩DP
- poj 1185 炮兵阵地 状态压缩dp
- POJ 1185 炮兵阵地 状态压缩dp
- poj 1185 炮兵阵地 【状态压缩dp】
- POJ--1185--炮兵阵地--状态压缩DP
- poj 1185 炮兵阵地(状态压缩DP)
- POJ 1185 炮兵阵地(状态压缩DP)
- poj 1185 炮兵阵地 状态压缩dp
- POJ - 1185 炮兵阵地 状态压缩DP
- 状态压缩DP POJ 1185 炮兵阵地
- POJ 1185 炮兵阵地 ( dp[状态压缩] )
- poj 1185 炮兵阵地 状态压缩dp
- js代码加密
- 有C++、Java、C#,为什么还要学C语言?
- android的jar包生成及使用
- freeRdp -----GDI加速扩展相关介绍
- OTGHNP_EventNotify
- 状态压缩DP POJ 1185 炮兵阵地
- RMAN duplicate创建Dataguard standby数据库并使用QMonitor监控standby delay
- [各种面试题] 请用Read4实现Read
- wince usb驱动中的OTGHNP_IsADevice函数
- code block 下链接mysql
- 如何加载显示jpg ,png bmp等图片,利用CImage
- C++实现设计模式: Factory 工厂模式
- stdcall调用约定
- 南阳理工学院csdn发展计划书