泪目,调了一下午的状压,强推,思维很纯粹

- [P2704 [NOI2001] 炮兵阵地](https://www.luogu.com.cn/problem/P2704)

希望你不认识她≥ω≤

题目大意:给一个n*m的图,然后其中有两种地形(H,P),平原地形(P)可以放置棋子,不同棋子之间存在制约关系,如下图

黑色的地形不可以放置,问最多可以放置多少个棋子。

分析地形:二维数组,0表示P,1表示H。

说说思路:因为每个位置存在两种情况(放置棋子/不放棋子),所以每种放置情况可以转化成一个二进制数,且m<10,最多存在(1<10)种状态。考虑限制条件后如下

int ghs(int h){//二进制数找有几个1int ss=0;while(h!=0){if(h&1)ss++;//位运算最后一位h=h>>1;//除以2}return ss;//返回当前状态的权重
}   for(int i=1;i<(1<<m);i++){//以二进制枚举所有的可能if(i&(i>>1)||i&(i>>2)||i&(i<<1)||i&(i<<2))continue;//已有‘1’左右两边不能放置st[++num]=i;//num状态int cpi=i;s[num]=ghs(cpi);
}

当(状态和地形)(状态和状态)进行&运算==0时,说明状态可以存在。需要提前枚举前两行。

状态受前两行分布的棋子影响。

写出递推式:dp[第i行][当前状态][上一行的状态]=max(dp[第i行][当前状态][上一行的状态],dp[上一行][上一行的状态][再上一行的状态](ps:这里最开始没明白状态枚举为什么是上一行而不是上两行,仔细观察递推式其实是因为至少回溯两行,判断条件需要上两行的状态,for的时候需要返回上一行判断,并加上这一行的权重)

 for(int i=1;i<=num;i++){//第一行if((st[i]&f[1])==0){//状态匹配dp[1][i][0]=s[i];}}//cout<<"yes"<<endl;for(int i=1;i<=num;i++){if((st[i]&f[2])==0){for(int j=1;j<=num;j++){if((st[i]&st[j])==0&&(st[j]&f[1])==0){dp[2][i][j]=s[i]+s[j];}}}}for(int i=3;i<=n;i++){//第n行for(int j=1;j<=num;j++){//枚举状态if((st[j]&f[i])==0){for(int p1=1;p1<=num;p1++){//上一行if((st[j]&st[p1])==0&&(st[p1]&f[i-1])==0){for(int p2=1;p2<=num;p2++){//再上一行if((st[j]&st[p2])==0&&(st[p1]&st[p2])==0&&(st[p2]&f[i-2])==0){dp[i][j][p1]=max(dp[i][j][p1],dp[i-1][p1][p2]+s[j]);}}}}}}}

最后ac代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[105][105],f[105],st[105],s[205],dp[105][105][105];
//a:图的输入 f:换算成二进制数的图 st:枚举所有的状态 s:状态所对应的每行权重 int ghs(int h){int ss=0;while(h!=0){if(h&1)ss++;h=h>>1;}return ss;
}
int main(){cin>>n>>m;char tmp;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>tmp;if(tmp=='H')a[i][j]=1;}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){f[i]=(f[i]<<1)+a[i][j];}}int num=0;st[++num]=0;for(int i=1;i<(1<<m);i++){if(i&(i>>1)||i&(i>>2)||i&(i<<1)||i&(i<<2))continue;st[++num]=i;int cpi=i;s[num]=ghs(cpi);}for(int i=1;i<=num;i++){//第一行if((st[i]&f[1])==0){//状态匹配dp[1][i][0]=s[i];}}//cout<<"yes"<<endl;for(int i=1;i<=num;i++){if((st[i]&f[2])==0){for(int j=1;j<=num;j++){if((st[i]&st[j])==0&&(st[j]&f[1])==0){dp[2][i][j]=s[i]+s[j];}}}}for(int i=3;i<=n;i++){//第n行for(int j=1;j<=num;j++){//枚举状态if((st[j]&f[i])==0){for(int p1=1;p1<=num;p1++){//上一行if((st[j]&st[p1])==0&&(st[p1]&f[i-1])==0){for(int p2=1;p2<=num;p2++){//再上一行if((st[j]&st[p2])==0&&(st[p1]&st[p2])==0&&(st[p2]&f[i-2])==0){dp[i][j][p1]=max(dp[i][j][p1],dp[i-1][p1][p2]+s[j]);}}}}}}}int ans=0;for(int i=1;i<=num;i++){for(int j=1;j<=num;j++){ans=max(ans,dp[n][i][j]);}}cout<<ans<<endl;
}//泪目

最近在按照洛谷的dp状压题单刷,大概每天一题吧,等到十一的周末(不放假555555)通过最近做过的题总结一下状压的基本思路和要点。之后会进行其他dp的练习。

目前会一点的dp:

1、各种背包

2、环形(环状)dp

3、树形dp

4、乱搞dp(我愿称之为shi上雕花)

P2704 [NOI2001] 炮兵阵地相关推荐

  1. C++ 洛谷 P2704 [NOI2001]炮兵阵地

    P2704 [NOI2001]炮兵阵地 没学状压DP的看一下 此题意思很简单,如下图,就是十字架上的不能有两个点放炮兵. 在做此题前,先做一下玉米田 玉米田题解 分析: 而m即一行的个数小于等于10, ...

  2. 洛谷 P2704 [NOI2001]炮兵阵地

    题目 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P& ...

  3. 洛谷P2704 [NOI2001]炮兵阵地(状压dp)

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P&quo ...

  4. jzoj1768,P2704,POJ1185-[NOI2001]炮兵阵地【状态压缩dp】

    正题 POJ链接:http://poj.org/problem?id=1185 jzoj链接:https://jzoj.net/senior/#main/show/1768 洛谷评测记录:https: ...

  5. [NOI2001]炮兵阵地

    Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H"  表示), 也可能是平原(用&q ...

  6. 洛谷 P2704 炮兵阵地 题解

    洛谷 P2704 炮兵阵地 题解 洛谷 P2704 题目 司令部的将军们打算在NNNMMM的网格地图上部署他们的炮兵部队.一个NNNMMM的地图由NNN行MMM列组成,地图的每一格可能是山地(用&qu ...

  7. 2022-5-20 吃月饼(something wrong), 数塔取数问题, 制铁棒, 子段统计, 炮兵阵地

    1. 吃月饼 有一块月饼,是正三角形的,又被分割成了许多块小正三角形的月饼,里面有若干块被吃掉了.现在想要在这块月饼中再找一个由小正三角形月饼的正三角形月饼,而且要求面积最大的. 样例解释: 大月饼的 ...

  8. POJ 1185 炮兵阵地 (状压DP)

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14869   Accepted: 5575 Description ...

  9. hdu4539 郑厂长系列故事——排兵布阵 + POJ1158 炮兵阵地

    题意: 郑厂长系列故事--排兵布阵 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Other ...

  10. poj 1185 NYOJ 85 炮兵阵地(状态压缩dp)

    炮兵阵地 时间限制:2000 ms  |  内存限制:65535 KB 难度:6 描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地 ...

最新文章

  1. 贵州大学明德学院计算机有多少班级,2014年贵州大学明德学院算机科学及信息系电子信息工程专业介绍...
  2. CSDN开源夏令营 百度数据可视化实践 ECharts(8)
  3. Linux驱动编程 step-by-step (十一)
  4. Core Data 编程指南
  5. pre2-flink单机部署与job提交
  6. 运行时间_运行一段时间报高压保护
  7. Linq to SQL 语法记录....并发写事务
  8. java 编辑器 开发工具_好的程序员有哪些实用的HTML5开发工具可以选择?
  9. java 路径不存在则创建_java中判断目录是否存在,若不存在则创建
  10. git 总是要求输入密码的问题
  11. FANUC NC GUIDE PRO 17.1虚拟机(XP系统)
  12. 多益网络校招 —— web前端笔试题
  13. hao916,hao123,2345.com浏览器劫持-分析与清除
  14. 再谈微软复兴,纳德拉与库克、马斯克、皮查伊在管理上有什么不同
  15. 荣耀4a鸿蒙,赵明:6 月起芯片供应将全面恢复,荣耀未来会考虑用华为鸿蒙系统...
  16. linux搭建web服务
  17. MySql生成日历表
  18. 关于死锁你了解多少,通过“让APP随手机壳改变颜色,程序员和产品经理大家”这一事,了解下死锁可好?
  19. 实验任务(五)---综合渗透
  20. 三菱串口PLC远程下载程序案例

热门文章

  1. 分时电价模型,削峰填谷,转移24小时一天中用电率,减少谷峰差
  2. Eloquen模型的具体使用方法
  3. C语言经典案例——第六章 字符串
  4. Lync日常运维常用命令
  5. fix-下拉出现白条问题
  6. C语言常见缩写和英文
  7. java 按钮响应回车_swing 设置回车响应按钮的方法
  8. ZZULIOJ:1148: 组合三位数之一
  9. gcc下fflush失效
  10. C++(opencv)简单拼接两幅图像