状压 DP 做题记录

1.普通状态压缩 DP

I.P1896 [SCOI2005] 互不侵犯

\(f_{i,j,st}\) 表示前 \(i\) 行中放置了 \(j\) 个国王,当前行状态为 \(st\) 的方案数。可以预处理出合法的状态与其 popcount,转移时枚举当前行状态和上一行状态,合法就转移。

const int N = 20,inf = 1e9,mod = 998244353;
const ll inff = 1e18;
int n,k,f[N][110][1000];
vector<int> v; int pcnt[1000];il void solve() {//------------code------------read(n,k);rep(st,0,(1 << n) - 1) if (!((st << 1) & st) && !((st >> 1) & st)) v.pb(st),pcnt[st] = __builtin_popcount(st);f[0][0][0] = 1;rep(i,1,n) for (auto st : v) for (auto stt : v)if (!(stt & st) && !((stt << 1) & st) && !((stt >> 1) & st)) {rep1(j,k,pcnt[st]) f[i][j][st] += f[i - 1][j - pcnt[st]][stt];}int ans = 0;for (auto st : v) ans += f[n][k][st];write(ans,'\n');// cerr << "Time : " << (db)(end - start) / CLOCKS_PER_SEC << " s" << endl;return ;
}

II.P2704 [NOI2001] 炮兵阵地

考虑将一行某个位置能否部署状压成一个二进制数,然后判断状态合法时可以直接把它们按位与起来。\(f_{i,st,st'}\) 表示前 \(i\) 行中,当前行状态为 \(st\),上一行状态为 \(st'\),最多能摆放的炮兵部队的数量。压掉一维就能过。

const int N = 110,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
int n,m,a[N];
int f[3][1034][1034];
vector<PII> v;il void solve() {//------------code------------read(n,m);rep(i,1,n) {string s; cin >> s;rep(j,0,m - 1) a[i] += (s[j] == 'H') * (1 << (m - 1 - j));}rep(st,0,(1 << m) - 1) if (!(st & (st >> 1)) && !(st & (st >> 2))) v.pb(st,__builtin_popcount(st));memset(f,-0x3f,sizeof f);for (auto x : v) f[1][x.fst][0] = x.snd;rep(i,2,n)for (auto st : v) if (!(st.fst & a[i]))for (auto stt : v) if (!(st.fst & stt.fst) && !(stt.fst & a[i - 1]))for (auto sttt : v) if (!(st.fst & sttt.fst) && !(stt.fst & sttt.fst) && !(sttt.fst & a[i - 2]))chmax(f[i % 3][st.fst][stt.fst],f[(i - 1) % 3][stt.fst][sttt.fst] + st.snd);int ret = 0;for (auto st : v) if (!(st.fst & a[n]))for (auto stt : v) if (!(st.fst & stt.fst) && !(stt.fst & a[n - 1]))chmax(ret,f[n % 3][st.fst][stt.fst]);write(ret,'\n');return ;
}

III.P1879 [USACO06NOV] Corn Fields G

板子。\(f_{i,st}\) 表示前 \(i\) 行中当前行状态为 \(st\) 的种植方案数。

const int N = 22,inf = 1e9,mod = 1e8;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
int n,m,a[N]; ll f[N][4100];
vector<int> v;il void solve() {//------------code------------read(n,m);rep(i,1,n)rep(j,1,m) {int x; read(x);a[i] += (1 << (m - j)) * (!x);}rep(st,0,(1 << m) - 1) if (!(st & (st << 1))) v.pb(st);f[0][0] = 1;rep(i,1,n)for (auto st : v) if (!(st & a[i]))for (auto stt : v) if (!(st & stt) && !(stt & a[i - 1]))f[i][st] = (f[i][st] + f[i - 1][stt]) % mod;ll ans = 0;for (auto st : v) ans = (ans + f[n][st]) % mod;write(ans,'\n');return ;
}

IV.P3052 [USACO12MAR] Cows in a Skyscraper G

\(f_{st}\) 表示当前已将哪些物品进行分组,最小的分组数量。维护一个当前 \(f_{st}\) 的最大剩余体积,每次能放下就放,放不下就增加组数,同时更新最大剩余体积。

const int N = 3e5 + 10,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
int n,m,w[20]; PII f[N];il void solve() {//------------code------------read(n,m);rep(i,1,n) read(w[i]);rep(st,1,(1 << n) - 1) f[st] = {-inf,inf};f[0] = {m,1};rep(st,1,(1 << n) - 1)rep(i,0,n - 1) if (st >> i & 1) {if (f[st].snd >= f[st ^ (1 << i)].snd && f[st ^ (1 << i)].fst >= w[i + 1]) {chmax(f[st].fst,f[st ^ (1 << i)].fst - w[i + 1]);f[st].snd = f[st ^ (1 << i)].snd;} else if (f[st].snd >= f[st ^ (1 << i)].snd + 1 && f[st ^ (1 << i)].fst < w[i + 1]) {chmax(f[st].fst,m - w[i + 1]);f[st].snd = f[st ^ (1 << i)].snd + 1;}// cerr << st << " " << i << " " << f[st].snd << '\n';}write(f[(1 << n) - 1].snd,'\n');return ;
}

V.P2396 yyy loves Maths VII

显然有 \(\mathcal{O(2^n n)}\) 的做法,但是 1 s 可能跑不过,考虑优化 \(n\) 的那一维,每次取出状态的 lowbit 来进行转移,并减掉它,这样可以减少大量无用的判断,能过此题。最慢的点跑了有 600 ms

const int N = 2e7 + 10,inf = 1e9,mod = 1e9 + 7;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
int n,m,a[N],b[3],f[N],g[N];il int lowbit(int x) { return x & -x; }il void solve() {//------------code------------read(n); rep(i,1,n) read(a[(1 << i - 1)]);read(m); rep(i,1,m) read(b[i]);f[0] = 1;rep(st,1,(1 << n) - 1) {g[st] = g[st ^ lowbit(st)] + a[lowbit(st)];bool fl = 1;rep(i,1,m) if (g[st] == b[i]) { fl = 0; break; }if (!fl) continue;int x = st;for (; x; x -= x & -x) f[st] = (f[st] + f[st ^ lowbit(x)]) % mod;}write(f[(1 << n) - 1],'\n');return ;
}

VI.P2831 [NOIP2016 提高组] 愤怒的小鸟

可以发现两个点可以唯一确定一条抛物线,预处理 \(sta_{i,j}\) 表示第 \(i\) 个点和第 \(j\) 个点组成的抛物线经过的点,对其做状压处理。现在就有一个 \(\mathcal{O(T2^n n^2)}\) 的做法,对于当前状态枚举接下来打哪条抛物线。这样并不能通过所有测试点,考虑优化。发现最终需要的答案是 \(f_{2^n - 1}\),其余有 \(f\) 对最终答案并没有贡献,那么它是无用的,显然我们最终状态 \(2^n - 1\) 在二进制下是有 \(n\)1 的,那么每次对于当前状态要推到最终状态,二进制下第一个为 0 的位置到最后一定会被转移掉,变为 1,那么我们就可以找到这个位置,再枚举它和其它的点的抛物线,用此抛物线的 \(sta\) 来转移就足矣。最后时间复杂度是 \(\mathcal{O(T2^n n)}\) 的。

const int N = 270010,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const db eps = 1e-8;
const ll inff = 1e18;
int n,m; pair<db,db> a[N];
int cnt[20][20],f[N];il void solve() {//------------code------------read(n,m);rep(i,1,n) cin >> a[i].fst >> a[i].snd;rep(i,1,n) rep(j,i + 1,n) {db x = a[i].fst,y = a[i].snd;db xx = a[j].fst,yy = a[j].snd;if (fabs(x - xx) < eps) { cnt[i][j] = cnt[j][i] = 0; continue; }db A = (y / x - yy / xx) / (x - xx),B = y / x - x * A;// cerr << i << " " << j << " " << A << " " << B << '\n';if (A >= 0) { cnt[i][j] = cnt[j][i] = 0; continue; }cnt[i][j] = 0;rep(k,1,n) if (fabs(A * a[k].fst * a[k].fst + B * a[k].fst - a[k].snd) < eps)cnt[i][j] += (1 << k - 1);cnt[j][i] = cnt[i][j];}rep(st,0,(1 << n) - 1) f[st] = inf;f[0] = 0;rep(st,0,(1 << n) - 2) {int p = -1;rep(i,0,n - 1) if (!(st >> i & 1)) { p = i; break; }chmin(f[st | (1 << p)],f[st] + 1);rep(i,1,n) if (i != p && ~cnt[p + 1][i]) chmin(f[st | cnt[p + 1][i]],f[st] + 1);}write(f[(1 << n) - 1],'\n');return ;
}

VII.P2473 [SCOI2008] 奖励关

显然有 \(f_{i,st}\) 表示前 \(i\) 次中,吃过的宝物的集合为 \(st\) 的最大期望分值。然后你会发现对于 \(f_i\),有一些状态是明显不合法的,此题起点唯一,但终点不唯一且有一些状态不可达的情况,所以需要倒推。

const int N = 20,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
int k,n,s[N],p[N];
db f[110][32770];il void solve() {//------------code------------read(k,n);rep(i,1,n) {read(p[i]); s[i] = 0;int x; read(x);while (x) {s[i] |= (1 << x - 1);read(x);}}f[k + 1][(1 << n) - 1] = 0;rep1(i,k,1)rep(st,0,(1 << n) - 1) {// cerr << i << " " << st << '\n';rep(j,1,n) if ((st & s[j]) == s[j]) f[i][st] += max((f[i + 1][st | (1 << j - 1)] + p[j] * 1.0),f[i + 1][st]) / (db)n;else f[i][st] += f[i + 1][st] / (db)n;}db ans = f[1][0];printf("%.6lf\n",ans);return ;
}

等待更新。

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

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

相关文章

SharePoint Online页面的一些奇怪参数

前言最近,在查找资料的时候,偶然间发现了一些非常有意思的参数,如下:?env=Embedded or ?env=WebView&wdStartOn=21.正经的SharePoint Online页面2.加了参数的SharePoint Online 页面3.加了另一个参数的SharePoint Online页面结束语相信大家看效果就已经发现了,参数是…

Alpha冲刺(2/14)——2024.11.13

目录一、团队成员分工与进度二、成员任务问题及处理方式三、冲刺会议内容记录会议内容四、GitHub签入记录及项目运行截图GitHub签入记录项目运行截图五、项目开发进展及燃尽图项目开发进展燃尽图六、团队成员贡献表 一、团队成员分工与进度成员 完成的任务 完成的任务时长 剩余…

PS端Flash固化

PS端Flash固化Vivado版本:Vivado2020.2 芯片型号:RFSoC XCZU47DR 前提条件:Vitis工程编译完成,拨码开关拨到PS JTAG模式创建引导镜像 首先右键应用工程系统,点击Create Boot Image。检查镜像工程的文件是否为固化需要的工程文件,点击创建镜像的选项即可完成创建,创建完成…

Office Word 文档格式与目录样式(毕业设计论文常用)

调整格式技巧: Word 中点击 “文件”--》"选项"--》“显示”,将高亮部分全部打钩,有利于查看格式字符、 “分页符” 和“分节符” 两个很有用, 其中分节符 前后的页码是独立的。 样式间的关系: 类比 C++ 中类的继承编写的伪代码,“正文”为基类,派生出 “论文…

想不到新版的onenote配色这么好看

原来一直在用office自带的onenote,想不到新版的onenote配色这么好看。

[豪の学习笔记] 计算机网络#001

计算机网络概念、网络协议、计算机网络结构、Internet结构、电路交换、多路复用、报文交换与分组交换1.1.1 - 什么是计算机网络 计算机网络 = 通信技术 + 计算机技术计算机网络就是一种特殊的通信网络 定义:计算机网络就是互联的、自治的计算机集合 自治:无主从关系 互联:互…

第十一次作业

1、RCE:分别实现ThinkPHP、Weblogic、Shiro漏洞的利用过程> ThinkPHP: 环境搭建前端测试是否存在pearcmd,访问路径,存在的话报错就确认存在在根目录下创建magedu3.php这个文件,文件内容为<?=phpinfo()?>,10.0.0.150:8080/public/?lang=../../../../../../../.…

Python并行编程1并行编程简介(上)高频面试题:GIL进程线程协程

1 并行编程简介 首先,我们将讨论允许在新计算机上并行执行的硬件组件,如 CPU 和内核,然后讨论操作系统中真正推动并行的实体:进程和线程。随后,将详细说明并行编程模型,介绍并发性、同步性和异步性等基本概念。 介绍完这些一般概念后,我们将讨论全局解释器锁(GIL)及其…

鸿蒙NEXT开发案例:年龄计算

​ 【引言】 本案例的目标是开发一款年龄计算器应用,该应用能够根据用户输入的出生日期,计算出用户的实际年龄、虚岁、星座、生肖等信息。同时,应用还将提供距离下次公历和农历生日的天数及星期等信息。为了实现这些功能,我们将使用ArkTS和ArkUI作为开发语言,并借助@nutpi…

Dosbox-x安装WinXP——图文教程

很多老游戏只能在win95、98或者XP中运行,因此,很多人尝试将Win95、98安装到Dosbox中,利用Dosbox来玩那些久远的情怀。有Win98自然就有人想在Dosbox中安装更高级的Win系统,于是就有人尝试在Dosnox中安装Win2000、WinXP的,其中2023-07-03在国外的fabulous.systems出现了一篇…

ABB AC900F学习笔记331:使用ST做自定义功能块,计算最近60秒的分钟均值和最近60分钟的小时均值

前面自己学习了在西门子TIA使用SCL编程,施耐德Unity中使用ST编程做分钟均值和小时均值的方法,今晚在家练习了在ABB Freelance中自定义功能块使用ST语言做分钟均值和小时均值。 新建项目、插入硬件、仿真器、操作站等不做介绍。新建一个用户功能块池,下面建一个功能块类。功能…

DBeaver如何设置自动刷新数据库表的数据,彻底解放双手!

前言 大家好,我是小徐啊。 DBeaver是一款常用的数据库连接工具,它的优点是免费使用,而且支持的数据库类型超级多,甚至可以直接安装数据库对应的驱动jar包来连接数据库。 比如达梦数据库,之前版本是可以通过jar包方式设置驱动来连接达梦数据库的。好了,言归正传,今天小徐…