POJ 1185 状态DP
这个题目是个挺难表示的状态DP,因为不但要考虑上下还要考虑左右,在DP里面就没有什么下了咯,但也至少除了考虑左右还要考虑上
所以先枚举出在同一行满足条件的状态 即 某状态 若 s&(s<<1) 或者(s&(s<<2)) 则说明同一行的炮塔在射击范围内,要去掉。
然后就是考虑不同行的了,只要上一行和上上行的状态不冲突即可
于是就有了如下状态
dp[i][j][k]代表第i行状态为k,上一行的状态为j时的最大值。
于是它的子状态就是 dp[i-1][w][j]代表上一行的状态为j 上上行的状态为w的最大值。
于是 dp[i][j][k]=max(dp[i][j][k],dp[i-1][w][j]+calc[k]) (calc代表某个状态中1的个数 即炮塔的数目)。
需要枚举四层循环 中间通过状态的对比来去掉一些没用的状态。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 11
using namespace std;
int dp[105][<<N-][<<N-];
int A[105],m,n,calc[<<N],num,state[<<N];
void init()
{
num=;
for (int i=;i<(<<m);i++)
{
int tmp=;
if (i&(i<<) || i&(i<<)) continue; //左右有冲突 跳过。
state[num]=i;
for (int j=;j<m;j++)
{
if ((<<j)&i)
tmp++;
}
calc[num++]=tmp; //算出某个状态中的含1的个数
}
}
bool fit(int a,int b)//判断上下某个状态是否冲突
{
if (a&b) return ;
return ;
}
void DP()
{
int ans=;
for (int i=;i<num;i++) //先预处理第一行的情况
{
if (!fit(state[i],A[]))
continue;
dp[][][i]=calc[i];
ans=max(ans,dp[][][i]);
}
for (int i=;i<=n;i++)
{
for (int k=;k<num;k++) //这里的是先枚举k还是j 没什么大关系,两个状态彼此独立。
{
for (int j=;j<num;j++)
{
if (!fit(state[j],state[k])|| !fit(state[k],A[i]) || !fit(state[j],A[i-]))//有冲突就直接跳过
continue;
for (int w=;w<num;w++)
{
if (!fit(state[j],state[w])|| !fit(state[k],state[w]))
continue;
if (!fit(state[w],A[i-])) continue;
dp[i][j][k]=max(dp[i][j][k],dp[i-][w][j]+calc[k]);
ans=max(ans,dp[i][j][k]);
}
}
}
}
printf("%d\n",ans);
}
int main()
{
char c; while (scanf("%d%d",&n,&m)!=EOF)
{
init();
memset(dp,,sizeof dp);
for (int i=;i<=n;i++)
{
getchar();
A[i]=;
for (int j=;j<m;j++)
{
c=getchar();
if (c=='H')
A[i]+=<<j; //这里故意把H设置为1,是为了正好用上面的fit函数,如果有状态把炮塔建在H上,就是不可取的状态。
// cout<<c;
}
// cout<<endl;
}
DP(); }
return ;
}
POJ 1185 状态DP的更多相关文章
- POJ 1185 状态压缩DP 炮兵阵地
题目直达车: POJ 1185 炮兵阵地 分析: 列( <=10 )的数据比较小, 一般会想到状压DP. Ⅰ.如果一行10全个‘P’,满足题意的状态不超过60种(可手动枚举). Ⅱ.用DFS ...
- POJ 1185 状态压缩DP(转)
1. 为何状态压缩: 棋盘规模为n*m,且m≤10,如果用一个int表示一行上棋子的状态,足以表示m≤10所要求的范围.故想到用int s[num].至于开多大的数组,可以自己用DFS搜索试试看:也可 ...
- poj 1185 状态压缩
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 27926 Accepted: 10805 Descriptio ...
- poj 1185(状态压缩DP)
poj 1185(状态压缩DP) 题意:在一个N*M的矩阵中,‘H'表示不能放大炮,’P'表示可以放大炮,大炮能攻击到沿横向左右各两格,沿纵向上下各两格,现在要放尽可能多的大炮使得,大炮之间不能相互 ...
- POJ 1185 炮兵阵地(状压DP)
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 26426 Accepted: 10185 Descriptio ...
- POJ 1185炮兵阵地 (状压DP)
题目链接 POJ 1185 今天艾教留了一大堆线段树,表示做不动了,就补补前面的题.QAQ 这个题,我第一次写还是像前面HDU 2167那样写,发现这次影响第 i 行的还用i-2行那样,那以前的方法就 ...
- POJ 3254 压缩状态DP
题意:一个矩形网格,可以填0或1, 但有些位置什么数都不能填,要求相邻两个不同时为1,有多少种填法.矩形大小最大 12*12. 压缩状态DP大多有一个可行的state的范围,先求出这个state范围, ...
- 【简●解】POJ 1185,LG P2704【炮兵阵地】
POJ 1185,LG P2704[炮兵阵地] 状压经典入门. [传送门] POJ 1185 洛谷 P2704 [题目大意] 司令部的将军们打算在 \(N\times M\) 的网格地图上部署他们的炮 ...
- hdu 4614 pieces 状态DP
题意:给你一个长度小于等于16的字符串,每次可以删除一个回文传,问你最少删除干净的字数. 状态+dp dp[i] = min(dp[i],dp[j]+dp[j^i]);(j是i的字串): 连接:htt ...
随机推荐
- 洛谷P1000 超级玛丽游戏(洛谷新手村1-1-1)
题目背景 本题是洛谷的试机题目,可以帮助了解洛谷的使用. 建议完成本题目后继续尝试P1001.P1008. 题目描述 超级玛丽是一个非常经典的游戏.请你用字符画的形式输出超级玛丽中的一个场景. *** ...
- 在 .net 中释放嵌入的资源
private static void ExtractResourceToFile(string resourceName, string filename) { if (!Syste ...
- 洛谷 P2426 删数
题目传送门 解题思路: 区间DP,f[i][j]表示区间i~j可获得的最大值,因为本题的所有区间是可以直接一次性把自己全删掉的,所以所有区间初始化为被一次性删除的值,然后枚举断点,跑区间DP. AC代 ...
- 2-Java基本数据类型和运算符
目录 Java基本类型 Java数据类型转换 Java运算符 1.Java基本类型 1.1.boolean布尔 - 只有true和false两种值,在内存中占1bits(位),默认是false 1.2 ...
- HDU 4902 Nice boat 多校4 线段树
给定n个数 第一个操作和普通,区间覆盖性的,把l-r区间的所有值改成固定的val 第二个操作是重点,输入l r x 把l-r区间的所有大于x的数,变成gcd(a[i],x) a[i]即指满足条件的序列 ...
- HDU 4862 JUMP 最小费用最大流
2014 多校的B题,由于我不怎么搞图论,当时碰到这个题目,我怎么想都没往网络流方面弄,不过网络流真的是个好东西,对于状态多变,无法用动规或者数据结构来很好表示的时候,非常有用 这个题目要求每个点一定 ...
- ACM-数细胞
题目描述:数细胞 一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数.编程需要用到的队列及其相关函数已经实现,你只需要完成 ...
- (二分查找)LowerBound
在包含size个元素的,从小到大顺序的int数组a里查找比给定整数p小的,下标最大的元素,找不到返回-1 题解: int LowerBound(int a[],int size,int p) { in ...
- oracle函数创建与调用
函数的定义: CREATE OR REPLACE FUNCTION FUNCTION_TEST(PARAMER1 IN VARCHAR, -- 参数的类型不写长度 PARAMER2 OUT VARCH ...
- Nmap目录扫描和漏洞扫描(9.27 第十三天)
目录扫描:扫描站点的目录,寻找敏感文件(目录名.探针文件.后台.robots.txt[].备份文件等) 目录:站点结构,权限控制不严格 探针文件:服务器配置信息,phpinfo.php readm ...