poj 1185 炮兵阵地(状态压缩DP)
来源:互联网 发布:浙商控股集团 知乎 编辑:程序博客网 时间:2024/06/01 10:20
【题目大意】类似于上面一道题,一个方格组成的矩阵,每个方格可以放大炮用0表示,不可以放大炮用1表示(原题用字母),让放最多的大炮,大炮与大炮间不会互相攻击。
【解析】可以发现,对于每一行放大炮的状态,只与它上面一行和上上一行的状态有关,每一行用状态压缩的表示方法,0表示不放大炮,1表示放大炮,同样的,先要满足硬件条件,即有的地方不能放大炮,然后就是每一行中不能有两个1的距离小于2(保证横着不互相攻击),这些要预先处理一下。然后就是状态表示和转移的问题了,因为是和前两行的状态有关,所以要开个三维的数组来表示状态,当前行的状态可由前两行的状态转移而来。即如果当前行的状态符合前两行的约束条件(不和前两行的大炮互相攻击),则当前行的最大值就是上一个状态的值加上当前状态中1的个数(当前行放大炮的个数)
【状态表示】dp[i][j][k] 表示第i行状态为k,第i-1状态为j时的最大炮兵个数。
【状态转移方程】dp[i][k][t] =max(dp[i][k][t],dp[i-1][j][k]+num[t]); num[t]为t状态中1的个数
【DP边界条件】dp[1][1][i] =num[i] 状态i能够满足第一行的硬件条件(注意:这里的i指的是第i个状态,不是一个二进制数,开一个数组保存二进制状态)
【解析】可以发现,对于每一行放大炮的状态,只与它上面一行和上上一行的状态有关,每一行用状态压缩的表示方法,0表示不放大炮,1表示放大炮,同样的,先要满足硬件条件,即有的地方不能放大炮,然后就是每一行中不能有两个1的距离小于2(保证横着不互相攻击),这些要预先处理一下。然后就是状态表示和转移的问题了,因为是和前两行的状态有关,所以要开个三维的数组来表示状态,当前行的状态可由前两行的状态转移而来。即如果当前行的状态符合前两行的约束条件(不和前两行的大炮互相攻击),则当前行的最大值就是上一个状态的值加上当前状态中1的个数(当前行放大炮的个数)
【状态表示】dp[i][j][k] 表示第i行状态为k,第i-1状态为j时的最大炮兵个数。
【状态转移方程】dp[i][k][t] =max(dp[i][k][t],dp[i-1][j][k]+num[t]); num[t]为t状态中1的个数
【DP边界条件】dp[1][1][i] =num[i] 状态i能够满足第一行的硬件条件(注意:这里的i指的是第i个状态,不是一个二进制数,开一个数组保存二进制状态)
#include <cstdio>#include <cstdlib>#include <algorithm>#include <iostream>using namespace std;char A[101][11];int state[1000],N,M,top = 0;int num[1000];int cpu[1000];int dp[101][1000][1000];//第二维为本行第三维为上一行int max(int a,int b){ return a > b ? a : b; }void Init(){ top = 0; int total = 1 << M; for(int i = 0;i < total;i ++) { if(!(i & i << 1) && !(i & i << 2)) state[++ top] = i; }}//初始化状态state[];void fox(){ for(int i = 1;i <= top;i ++) { int tmp = state[i]; while(tmp){ if(tmp & 1) num[i] ++; tmp = tmp >> 1; } }}//初始化各个状态对应的炮台数;int main(){ int i,j,k,a; cin >> N >> M; for(i = 1;i <= N;i ++) for(j = 1;j <= M;j ++) cin >> A[i][j]; Init(); fox(); printf("1"); for(i = 1;i <= N;i ++) for(j = 1;j <= M;j ++) { if(A[i][j] == 'H') cpu[i] += 1 << (j-1); } for(i = 1;i <= top;i ++)//初始化第一行的情况上一行为0 { if(!(state[i] & cpu[1])) dp[1][i][1] += num[i]; } for(i = 1;i <= top;i ++) { if(!(state[i] & cpu[2])) for(j = 1;j <= top;j ++) if(!(state[j] & cpu[1]) && !(state[j] & state[i])) dp[2][i][j] = dp[1][j][1] + num[i]; } for(i = 3;i <= N;i ++) for(j = 1;j <= top;j ++) for(k = 1;k <= top;k ++) if(!(state[j] & cpu[i]) && !(state[k] & cpu[i-1]) && !(state[j] & state[k])) for(a = 1;a <= top;a ++) { if(!(state[a] & cpu[i-2]) && !(state[a] & state[j]) && !(state[k] & state[a])) dp[i][j][k] =max(dp[i][j][k] , dp[i-1][k][a] + num[j]); } int ans = 0;//三维的都不超时,也是蛮拼的,估计是top,不给力 for(i = 1;i <= top;i ++) for(j = 1;j <= top;j ++) ans = max(ans,dp[N][i][j]); printf("%d\n",ans); return 1;}
0 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
- 新的开始
- 堆和栈
- 【trie】hdu 3460 Ancient Printer
- 'scanf' was declared deprecated,
- 内联函数、外联函数
- poj 1185 炮兵阵地(状态压缩DP)
- ACdream 1216 (ASC训练1) Beautiful People(DP)
- 反汇编的应用1-软件破解
- 将中文数字转换成英文表示
- heightCanBeGuessed的错误处理
- C语言_全局变量/静态全局变量_局部变量/静态局部变量
- Ubuntu安装配置Python.pyDev
- JS基础——函数的创建和使用
- Cocos2d-X中的字体