acwing算法提高之动态规划--状态压缩DP

目录

  • 1 基础知识
  • 2 模板
  • 3 工程化

1 基础知识

暂无。。。

2 模板

暂无。。。

3 工程化

题目1:小国王。

解题思路:状态压缩DP。

状态定义f[i][j][a]:表示已经考虑了前i行,并且摆放了j个国王,且第i行的状态是a的总方案数。

定义第i行的合理状态a:二进制表示中没有连续的两个1。与第i-1行不冲突,比如第i-1行的状态是b,那么需要满足a & b == 0a | b没有连续的两个1。

状态转移,先计算出所有合法的状态,存储在向量states中,然后预先处理出每个状态a可以从状态b转移过来unordered_map<int, vector<int>> g

C++代码如下,

#include <iostream>
#include <vector>
#include <unordered_map>using namespace std;const int N = 12, M = 1 << N;
int n, m;
long long f[N][N*N][M];
vector<int> states; //合法的状态
unordered_map<int,vector<int>> g;bool check(int x) {//是否存在连续的两个1for (int i = 0; i < 31; ++i) {if ((x >> i & 1) && (x >> (i + 1) & 1)) {return false; //非法的状态}    }return true;
}int get_cnt(int x) {//二进制中1的个数int res = 0;for (int i = 0; i < 31; ++i) {if (x >> i & 1) res += 1;}return res;
}int main() {cin >> n >> m;for (int i = 0; i < 1 << n; ++i) {if (check(i)) {states.emplace_back(i);}}for (auto a : states) {for (auto b : states) {if ((a & b) == 0 && check(a | b)) {g[a].emplace_back(b);}}}//初始化状态f[0][0][0] = 1;for (int i = 1; i <= n + 1; ++i) {for (int j = 0; j <= m; ++j) {for (auto a : states) {for (auto b : g[a]) {int cnt = get_cnt(a);if (j >= cnt) {f[i][j][a] += f[i-1][j-cnt][b];}}}}}cout << f[n+1][m][0] << endl;return 0;   
}

题目2:玉米田。

状态定义f[i][a]:考虑前i行,且第i行的状态是a的所有方案数。

第i行的状态a需要满足:二进制表示中没有两个相邻的1。与第i-1行的状态b不冲突,即(a & b) == 0。只能在肥沃的土地种玉米。

可以预处理出合法的状态,存储在向量states中,然后考虑每一行的肥沃土地,可以换一种思路,将贫瘠的土地构成的状态记为row[i],则需要满足(a & row[i]) == 0

C++代码如下,

#include <iostream>
#include <vector>
#include <unordered_map>using namespace std;const int N = 15, M = 1 << N, mod = 1e8;
int n, m;
vector<int> row; //表示不育
vector<int> states;
unordered_map<int, vector<int>> g; //状态a可以由状态b转移过来
int f[N][M];bool check(int x) {for (int i = 0; i < 31; ++i) {if ((x >> i & 1) && (x >> (i + 1) & 1)) {return false; //非法状态}}return true; //合法状态
}int main() {cin >> n >> m; //n行m列row.emplace_back(0);for (int i = 0; i < n; ++i) {int t = 0;for (int j = 0; j < m; ++j) {int x;cin >> x;if (x == 0) {t += 1 << j;}}row.emplace_back(t);//不育}for (int i = 0; i < 1 << m; ++i) {if (check(i)) {states.emplace_back(i);}}for (auto a : states) {for (auto b : states) {if ((a & b) == 0) {g[a].emplace_back(b);}}   }//状态计算f[0][0] = 1;for (int i = 1; i <= n + 1; ++i) {for (auto a : states) {if (a & row[i]) continue;for (auto b : g[a]) {if (b & row[i-1]) continue;if ((a & b) == 0) {f[i][a] = (f[i][a] + (f[i-1][b] % mod)) % mod;}}}}cout << f[n+1][0] << endl;return 0;
}

题目3:炮兵阵地。

解题思路:状态压缩DP。由于空间有限,所以需要用到滚动数组,在原地址上更新滚动数组,暂时没有理解到本质,先空着

状态定义f[i][a][b]:考虑前i行,且第i-1行的状态是a,第i行的状态是b,该case下的最大摆放炮兵的数目。

合法状态:两个1之间至少空了2个位置。第i行、第i-1行和第i-2行任意两个不能互相攻击到,记第i-1行的状态为a,第i行的状态为b,第i-2行的状态为c,那么有((a & b) | (a & c) | (b & c)) == 0

同时,还有一个额外需要考虑的,就是山顶不能放置炮兵,记第i行山顶的状态为row[i],那么需要满足(b & row[i]) == 0

C++代码如下,

#include <iostream>
#include <vector>
#include <cstring>
#include <unordered_map>using namespace std;const int N = 110, M = 1 << 12;int n, m;
vector<int> states;
vector<int> row(N, 0);
int f[2][M][M];bool check(int x) {for (int i = 0; i < 31; ++i) {if ((x >> i & 1) && ((x >> (i + 1) & 1) || (x >> (i + 2) & 1))) {return false; //非法状态}}return true;
}int get_count(int x) {int res = 0;for (int i = 0; i < 31; ++i) {if (x >> i & 1) res += 1;}return res;
}int main() {cin >> n >> m;for (int i = 1; i <= n; ++i) {int t = 0;for (int j = 0; j < m; ++j) {char c;cin >> c;if (c == 'H') {t += 1 << j;}}row[i] = t;}//处理合理状态for (int i = 0; i < 1 << m; ++i) {if (check(i)) {states.emplace_back(i);}}//计算状态for (int i = 1; i <= n; ++i) {for (auto a : states) {//第i-1行的状态是afor (auto b : states) { //第i行的状态是bfor (auto c : states) {//第i-2行的状态是cif ((a & row[i-1]) || (b & row[i])) continue; //山上不能放置炮兵if ((a & b) || (a & c) || (b & c)) continue; //行与行之间不能攻击到f[i & 1][a][b] = max(f[i & 1][a][b], f[i - 1 & 1][c][a] + get_count(b));}}}}int res = 0;for (auto a : states) {for (auto b : states) {res = max(res, f[n & 1][a][b]);}}cout << res << endl;return 0;
}

题目4:愤怒的小鸟。

解题思路:没有看懂,有时间再推敲

C++代码如下,

#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>#define x first
#define y secondusing namespace std;typedef pair<double, double> PDD;const int N = 18, M = 1 << N;
const double eps = 1e-8;int n, m;
PDD q[N];
int path[N][N];
int f[M];int cmp(double x, double y) {if (fabs(x - y) < eps) return 0;if (x < y) return -1;return 1;
}int main() {int T;cin >> T;while (T--) {cin >> n >> m;for (int i = 0; i < n; ++i) cin >> q[i].x >> q[i].y;memset(path, 0, sizeof path);for (int i = 0; i < n; ++i) {path[i][i] = 1 << i;for (int j = 0; j < n; ++j) {double x1 = q[i].x, y1 = q[i].y;double x2 = q[j].x, y2 = q[j].y;if (!cmp(x1, x2)) continue;double a = (y1 / x1 - y2 / x2) / (x1 - x2);double b = y1 / x1 - a * x1;if (cmp(a, 0) >= 0) continue;int state = 0;for (int k = 0; k < n; ++k) {double x = q[k].x, y = q[k].y;if (!cmp(a * x * x + b * x, y)) state += 1 << k;}path[i][j] = state;}}memset(f, 0x3f, sizeof f);f[0] = 0;for (int i = 0; i + 1 < 1 << n; ++i) {int x = 0;for (int j = 0; j < n; ++j) {if (!(i >> j & 1)) {x = j;break;}}for (int j = 0; j < n; ++j) {f[i | path[x][j]] = min(f[i | path[x][j]], f[i] + 1);}}cout << f[(1 << n) - 1] << endl;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/228167.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

qt程序在Linux下打包的一般流程

编译 手动编写编译脚本 qmake make复制依赖库 参考文章&#xff1a; https://blog.csdn.net/JOBbaba/article/details/124289626 https://zhuanlan.zhihu.com/p/49919048 复制系统依赖库 编写复制脚本copy.sh ldd复制Qt依赖库 主要是libqxcb.so的相关依赖需要复制&…

流量分析基础

定义&#xff1a; 流量分析&#xff08;Traffic Analysis&#xff09;是指对网络流量数据进行分析和解释&#xff0c;以获得有关网络中通信的信息和情报。这种技术可以用于网络安全、网络管理和网络优化等领域。 网络流量包含了许多有关网络通信的细节信息&#xff0c;如源IP地…

Linux c++开发-06-使用Linux API 进行文件的读写

先简单的介绍一下open,read,write 先用open接口去打开文件&#xff0c;flag表示打开文件的权限不同。 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);示例 结果&#xff1a;

AD9361 Evaluation Software配置脚本转换工具

最近在玩一个开源的AD9361项目&#xff0c;AD9361采用纯逻辑配置&#xff0c;不需要ARM或者MicroBlaze。其中&#xff0c;先是用AD9361 Evaluation Software生成配置脚本&#xff0c;再转换成ad9361_lut.v。 在网上查了一圈&#xff0c;有个转换工具叫bit_converter&#xff0…

经典深度学习算法【1】:K-近邻算法(KNN)概述

最简单最初级的分类器是将全部的训练数据所对应的类别都记录下来&#xff0c;当测试对象的属性和某个训练对象的属性完全匹配时&#xff0c;便可以对其进行分类。但是怎么可能所有测试对象都会找到与之完全匹配的训练对象呢&#xff0c;其次就是存在一个测试对象同时与多个训练…

跟我学c++高级篇——C++26反射预览

一、c23的反射跳票 本来按照预定&#xff0c;c23中反射就应该比较全的。结果&#xff0c;由于众所周知的原因&#xff0c;线上会议肯定是不如线下会议效率高&#xff0c;那么反射这种对于c不太急切的功能&#xff08;当然&#xff0c;也有其它原因&#xff09;只能向后放一放。…

迭代器的分类

迭代器的分类&#xff1a; 这里的前置后置递增是a和a&#xff1b; 这里的前值后置递减是a--和--a&#xff1b; 各迭代器的继承关系&#xff1a; 当使用双向迭代器时&#xff0c;可以使用随机迭代器&#xff1b;

THEMIS---Beta Sprint Summary Essay Blog

Which course does this assignment belong to2301-MUSE社区-CSDN社区云What are the requirements for this assignmentbeta SprintThe goal of this assignmentTo summarize the beta task progress and the teams sprintsTeam NameThemisTop-of-the-line collection of essa…

架构师和软件架构

架构师和软件架构 引言 在今天的数字化世界中&#xff0c;软件已成为我们生活和工作的不可或缺的一部分。从简单的应用程序到复杂的系统&#xff0c;软件的设计和开发过程都需要精心的规划和管理。这里&#xff0c;软件架构的概念和软件架构师的角色就显得尤为重要。 软件架…

maui中实现加载更多 RefreshView跟ListView 跳转到详情页 传参(3)

效果如图 这里的很多数据是通过传参过来的的。 代码 例表页加入跳转功能&#xff1a; <ListView ItemsSource"{Binding Items}" ItemAppearing"OnItemAppearing" ItemTapped"OnItemTapped" RowHeight"70" Margin"20"…

visual studio 2019 移除/卸载项目已经如何再加载项目

文章目录 移除解决方案下的某个项目添加已移除的项目移除项目加载已卸载的项目注意事项 移除解决方案下的某个项目 在项目名称上&#xff0c;点击鼠标右键&#xff0c;弹出右键工具栏&#xff0c;找到 移除 功能。 然后鼠标左键点击 移除。 弹出的模态框&#xff0c;选择确定…

代码随想录刷题题Day15

刷题的第十五天&#xff0c;希望自己能够不断坚持下去&#xff0c;迎来蜕变。&#x1f600;&#x1f600;&#x1f600; 刷题语言&#xff1a;C Day15 任务 ● 513.找树左下角的值 ● 112. 路径总和 113.路径总和ii ● 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历…

MYSQL备份和恢复

数据库的备份和恢复&#xff1a; 备份&#xff1a;完全备份 增量备份 完全备份&#xff1a;将整个数据库完整的进行备份 增量备份&#xff1a;在完全备份的基础之上&#xff0c;对后续新增的内容进行备份 备份的需求&#xff1a; 在生产环境中&#xff0c;数据的安全至关重…

Docker安装Redis哨兵

目录 Redis哨兵 一、哨兵模式的主要概念和组件 二、哨兵模式的工作流程 三、哨兵配置流程 1、创建Redis哨兵配置文件 2、启动哨兵 3、命令解读 4、 查看哨兵是否正常启动 5、测试主机宕机 四、哨兵运行流程 五、哨兵选举算法 六、哨兵使用建议 Redis哨兵 Redis哨兵…

josef约瑟 时间继电器 DS-23/C AC220V 10S柜内板前接线

系列型号&#xff1a; DS-21时间继电器 &#xff1b;DS-22时间继电器&#xff1b; DS-23时间继电器&#xff1b;DS-24时间继电器&#xff1b; DS-21C时间继电器&#xff1b;DS-22C时间继电器&#xff1b; DS-23C时间继电器&#xff1b; DS-25时间继电器&#xff1b;DS-26…

python/c++ Leetcode题解——746. 使用最小花费爬楼梯

目录 方法一&#xff1a;动态规划 复杂度分析 方法一&#xff1a;动态规划 假设数组 cost 的长度为 n&#xff0c;则 n 个阶梯分别对应下标 0 到 n−1&#xff0c;楼层顶部对应下标 n&#xff0c;问题等价于计算达到下标 n 的最小花费。可以通过动态规划求解。 创建长度为 n…

springboot 学习网站

Spring Boot 系列教程https://www.docs4dev.com/ Spring Boot 教程汇总 http://www.springboot.wiki/ Spring Cloud 微服务教程 http://www.springboot.wiki/ 1、自定义banner   https://www.cnblogs.com/cc11001100/p/7456145.html 2、事件和监听器   https://blog.csd…

孩子都能学会的FPGA:第三十三课——用FPGA实现一个通用的SPI主机接收模块

&#xff08;原创声明&#xff1a;该文是作者的原创&#xff0c;面向对象是FPGA入门者&#xff0c;后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门&#xff0c;作者不光让大家知其然&#xff0c;还要让大家知其所以然&#xff01;每个工程作者都搭建了全自动化的仿…

如何从 iPhone 上恢复已删除的照片教程分享

您是否错误地删除了 iPhone 上的错误照片&#xff1f;或者您可能已将手机恢复出厂设置&#xff0c;但现在所有照片都消失了&#xff1f;如果您现在遇到这样的情况&#xff0c;我们可以为您提供解决方案。 在本文中&#xff0c;我们将向您展示七种数据恢复方法&#xff0c;可以…

人工智能驱动化学品创新设计的实践与展望

改进化学品研发模式&#xff0c;缩短化学品从发现到应用的时间是化工行业中所有科学研究者和产业人员的最终目 标。本文提出&#xff1a;化学品设计是一个涉及多组分、多尺度和多物理场的复杂过程&#xff0c;现有的实验研究模式难以深入高 效地揭示相关的物理化学机制&#xf…