[状压dp] 炮兵阵地(状压dp)
文章目录
- 0. 前言
- 1. 状压dp+棋盘式(基于连通性)
0. 前言
相关:
- [状压dp] 蒙德里安的梦想(模板题+状压dp)
强相关:
- [状压dp] 小国王(状压dp)
- [状压dp] 玉米田(状压dp)
1. 状压dp+棋盘式(基于连通性)
292. 炮兵阵地
[状压dp] 玉米田(状压dp) 是高度为 1 的十字形,本题是 高度为 2 的十字形。 那么状态转移就和前 2 层有关。且本题是求最大值,而非方案数。
思路:
- 状态定义:
f[i][j][k]
:摆放完前i
行,且第i-1
行摆放状态是j
,第i
行摆放状态是k
的所有摆放方案的最大值
- 状态计算:
假设第
i
行状态是b
,第i-1
行状态是a
,第i-2
行状态是c
当
((a&b) | (a&c) | (b&c)) = 0
则说明纵向不会出现冲突当
(g[i-1]&a | g[i]&b)=0
则说明炮兵在平地上。在此与的优先级高于或的优先级,不用加括号状态转移方程:
f[i][j][k] = max(f[i][j][k], f[i-1][c][j]+cnt[c])
- 时间复杂度: n∗2m∗2m∗2m=O(n23m)=100∗230=1011n*2^m*2^m*2^m=O(n2^{3m})=100*2^{30}=10^{11}n∗2m∗2m∗2m=O(n23m)=100∗230=1011 这个时间复杂度…但是里面合法状态很少…依旧可以过
滚动数组优化,不然空间直接爆炸。
重点还是在状态定义及状态计算上。这里状态定义记录了第 i
行状态为 k
、第 i-1
行状态为 j
。那么找到最后一个不一样的点就是第 i-2
行,所以就依据第 i-2
行进行状态划分即可。
代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>using namespace std;const int N = 11, M = 1 << 10;int n, m;
int g[105];
vector<int> state;
int cnt[M];
int f[2][M][M]; // 使用滚动数组,后两维都已经100w了...bool check(int x) {for (int i = 0; i < m; ++i) // 针对列做状态压缩,同列三个不能有2个1if ((x >> i & 1) && ((x >> i + 1 & 1) | (x >> i + 2 & 1)))return false;return true;
}int count(int x) {int res = 0;for (int i = 0; i < m; ++i) res += x >> i & 1;return res;
}int main() {cin >> n >> m;for (int i = 1; i <= n; ++i)for (int j = 0; j < m; ++j) {char c; // 拿int类型读入char,读入全是0cin >> c;if (c == 'H')g[i] += 1 << j; // 二进制表示一行}for (int i = 0; i < 1 << m; ++i) if (check(i)) {state.push_back(i);cnt[i] = count(i);}for (int i = 1; i <= n + 2; ++i)for (int j = 0; j < state.size(); ++j) // j为第i-1行状态for (int k = 0; k < state.size(); ++k) // k为第i行状态for (int u = 0; u < state.size(); ++u) { // u为第i-2行状态int a = state[j], b = state[k], c = state[u];if ((a & b) | (b & c) | (a & c)) continue; if (g[i - 1] & a | g[i] & b) continue;f[i & 1][j][k] = max(f[i & 1][j][k], f[i - 1 & 1][u][j] + cnt[b]);}cout << f[n + 2 & 1][0][0] << endl;// 遍历写法,修改第一个 for (int i = 1; i <= n; ++i)/*int res = 0;for (int i = 0; i < state.size(); ++i) for (int j = 0; j < state.size(); ++j)res = max(res, f[n & 1][i][j]);cout << res << endl;*/return 0;
}
[状压dp] 炮兵阵地(状压dp)相关推荐
- POJ - 1185 炮兵阵地(状压dp)
题目链接:点击查看 题目大意:中文题,题意很清晰,不多赘述 题目分析:最基础的状压dp,需要考虑如何转移,因为每一个炸弹所涉及的范围都是上下左右两个格子,我们可以从第一行开始向下转移,这样某一行的状态 ...
- POJ 1185 炮兵阵地 (状压DP)
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 14869 Accepted: 5575 Description ...
- POJ1185 炮兵阵地 状压DP
炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 31819 Accepted: 12295 Descriptio ...
- POJ 1185 炮兵阵地(状态压缩DP)
Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用&quo ...
- 玉米田 炮兵阵地 状态压缩DP
玉米田 原题 #include <cstring> #include <iostream> #include <algorithm> #include <ve ...
- POJ1185炮兵阵地(状态压缩 + dp)
题目链接 题意:给出一张n * m的地图,其中 有的地方能放大炮,有的地方不能,大炮与上下左右两个单位范围内会相互攻击,问最多能放几个大炮 能放大炮为1不能放大炮为0,把每一行看做一个状态,要除去同一 ...
- 洛谷P2704 [NOI2001]炮兵阵地(状压dp)
题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P&quo ...
- P2704 炮兵阵地 (状压dp入门题) 题解
题意简述:给定一个大小为n*m的棋盘,棋盘上'H'表示不可放置,'P'表示可放置,一个棋子在棋盘上的攻击范围是其左右上下2格以内,求不冲突情况下的最多摆放棋子数. 分析:决策是对于一个P格子考虑放或不 ...
- POJ 1185 炮兵阵地 状压dp
http://poj.org/problem?id=1185 经典题目不必多说,直接贴代码. 1 #include<cstdio> 2 #include<cstring> 3 ...
- 状压dp之二之三 炮兵阵地/玉米田 By cellur925
一.简单的状压dp 玉米田 题目描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ ...
最新文章
- centos7 解决chrome提示您的连接不是私密连接的方法
- 给开源编译器插入后门
- oracle和mysql查询_Oracle和MySQL分组查询GROUP BY
- pip安装的库导入pycharm中
- 关卡 动画 蓝图 运行_UE4无缝过场动画
- Springboot应用中线程池配置教程(2021版)
- 使用Jenkins在Azure Web App上进行ASP.NET Core应用程序的持续集成和部署(CI/CD)–第4天
- TensorFlow2.0:tensorboard使用
- 累计增量备份策略_SAN存储做定时/实时备份的介绍
- BZOJ4659 Lcm
- 斐讯盒子N1_YYF_刷机ROM_讯飞语音助手实用版固件及教程分享
- Android 调用语音模块
- apple tv 开发_如何在Apple TV上重新排列,添加和删除频道
- 第十节 项目风险、收尾、知识产权管理
- 【vue】To install them, you can run: npm install --save aws-sdk module
- 摩拜免押金是在阿里的哈罗猛烈攻击下的应对举措
- 「雷锋前线」迅雷的“星域CDN”能撼动市场吗?
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十六):AccessToken自动管理机制
- 将 Debian APT 引入 iPhone
- 欧拉旋转矩阵角速度雅克比