洛谷$P3959\ [NOIp2017]$ 宝藏 状压$dp$】的更多相关文章

正解:状压$dp$ 解题报告: 传送门$QwQ$ $8102$年的时候就想搞这题了,,,$9102$了$gql$终于开始做这题了$kk$ 发现有意义的状态只有当前选的点集和深度,所以设$f_{i,j}$表示当前深度为$i$,选了的点集状态为$j$. 然后转移就$f_{i,S}=min(f_{i-1,S_0}+cost)$,其中$S_0$为$S$的子集,$cost$为$S\ xor\ S_0$中的所有点和$S_0$的连边乘以$i$. 正确性显然?然后说下就,这里是并没有限制一定是和第$i-1$层的…
题目:https://www.luogu.org/problemnew/show/P3959 搜索: 不是记忆化,而是剪枝: 邻接矩阵存边即可,因为显然没有那么多边. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; ll const inf=0x3f3f3f3f3…
洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复杂 只是存状态有点难想到 思路 因为n最大为12 所以可以想到是状压 因为n<=12 所以可以用邻接矩阵存下图 枚举每个点作为起点开始DFS 注意每次DFS的初始化和赋值问题即可 代码 #include<iostream> #include<cstdio> #include<…
之前写了一份此题关于模拟退火的方法,现在来补充一下状压dp的方法. 其实直接在dfs中状压比较好想,而且实现也很简单,但是网上有人说这种方法是错的...并不知道哪错了,但是就不写了,找了一个正解. 正解的区别在于状态,(树高是啥意思),每次都是从当前状态的子集转移过来.这里用到了快速枚举子集的操作,很值得写一下. 题干: 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 nnn 个深埋在地下的宝藏屋, 也给出了这 nnn 个宝藏屋之间可供开发的m mm 条道路和它们的长度. 小明决心…
[题目描述] 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋,也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但是,每个宝藏屋距离地面都很远,也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路则相对容易很多. 小明的决心感动了考古挖掘的赞助商, 赞助商决定免费赞助他打通一条从地面到某个宝藏屋的通道,通往哪个宝藏屋则由小明来决定. 在此基础上, 小明还需要考虑如何开凿宝藏屋之间的道路.…
[NOIP2017]宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多. 小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某 个宝藏屋的通道,通往哪个宝藏屋则由小明来决定. 在此基础上,小明还需要考虑…
简单的状压DP,和NOIP2017 Day2 找宝藏 代码几乎一样.(比那个稍微简单一点) f[i][j] ,i代表点的状态,j是当前选择的点,枚举上一个选到的点k 然后从f[i-(1<<(j-1))][k]转移到f[i][j]即可 方程f[i][j]=max(f[i][j],[k]+B[k][j]+A[j]); 注意的点1.开longlong 2.数据不保证X[i]和Y[i]都不同,也不保证X[i]不等于Y[i],这里很坑要加特判. #include<cstdio> #inclu…
题目传送门:https://www.luogu.org/problemnew/show/P3959 题意:给出一个有$N$个点的图,求其中的一个生成树(指定一个点为根),使得$\sum\limits_{i=1}^{N-1} v_i \times dep_i$最小,其中$v_i$为生成树上某条边的边权,$dep_i$为这条边连接的两个点中深度较浅的点的深度.$N \leq 12 , v \leq 5 \times 10^5$ $N \leq 12$给我们一个很强烈的信息:状态压缩 (所以这题还可以…
时隔多年终于把这道题锅过了 数据范围显然用搜索剪枝状压dp. 可以记还有哪些点没到(或者已到了哪些点).我们最深已到的是哪些点.这些点的深度是多少,然后一层一层地往下推. 但其实是没必要记最深的那一层的,只要强行装作每次更新都是用最深的深度更新就可以.这样的话,虽然会有很多情况偏大,但是能正确更新的情况其实是都已经包括了. 因为你如果想以当前状态去更新,但用的还不是最深一层的点的话,干脆就可以在之前你想用那个点处于最后一层的时候去更新. 代码写的很捉急..最后常数也很捉急... #include…
Description 你有一个长方形的地图,每一个格子要么是一个障碍物,要么是一个有一定价值的宝藏,要么是一个炸弹,或者是一块空地.你的初始位置已经给出.你每次可以走到上.下.左.右这四个相邻的格子.你不允许走出这幅地图,不允许进入有宝藏.障碍物或是炸弹的地方.你需要规划一个闭合的路线(起点和终点都必须在初始位置)来取得宝藏.注意这个路线围成的多边形中不可以包含炸弹.假设路线围成的多边形包含的所有宝藏的价值之和为v,并且你从起点到终点走了 k步(从一个格子走到旁边的格子算作一步),那么你沿该路…
题解 真的想不到这题状压的做法...听说还有跑的飞快的模拟退火,要是现场做绝对滚粗QAQ. 不考虑深度,先预处理出 $pt_{i, S}$ 表示让一个不属于 集合 $S$ 的 点$i$ 与点集 $S$ 联通的最小代价, 也就是从 $i$ 到 $ j, j \in S$的最小距离. 接着处理$ss_{S, T}$, $S\subset T$, 表示从集合$S$拓展到$T$所需要的最小代价. 最后求出$f_{i, j}$ 表示当前已到 深度$i$, 已经扩展到集合$S$时耗费的最小代价. 答案就是$…
题目:https://www.luogu.org/problemnew/show/P2473 还是对DP套路不熟悉... 像这种前面影响后面,而后面不影响前面的问题就应该考虑倒序递推: 看n只有15那么考虑状压,期望什么的就是除一下n就行了. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; ],cnt[],s[]; ][<<]; int main…
题目:https://www.luogu.org/problemnew/show/P3112 状压DP...转移不错. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; ll <<),inf=1e18; ll n,H,h[],w[],s[],f[maxn…
链接 : Here! 思路 : 状压DP. 开始想直接爆搜, T掉了, 然后就采用了状压DP的方法来做. 定义$f[S]$为集合$S$的最小代价, $dis[i]$则记录第$i$个点的"深度", 所以说边$E{[i, j]}$ 的工程代价就为$dis[i] * E{[i, j]}$, 因此可以得到状态转移方程 : 初始状态(假设以$i$作为起点) : $dis[i] = 1$, $f[1 << (i - 1)] = 0$, $dis[k] = INF (k != i, k…
附带其他做法参考:随机化(模拟退火.爬山等等等)配合搜索剪枝食用. 首先题意相当于在图上找一颗生成树并确定根,使得每个点与父亲的连边的权乘以各自深度的总和最小.即$\sum\limits_{i}depth_i\times value_{i→fa}$. 看数据范围想状压,固定好一个点为根,然后每个点选没选看做状态$0/1$压位,于是朴素思想是$f[S][S_0][d]$表示已经选了$S$,当前$d$层选了$S'$($S'\subset S$),这样一定可以保证由$S'$导出第$d+1$层,更新答案…
题目描述 分析 比较简单的状压DP 我们设\(f[i][j]\)为当前的状态为\(i\)且当前所在的位置为\(j\)时走过的最小距离 因为老鼠的坐标为\((0,0)\),所以我们要预处理出\(f[1<<(i-1)][i] (1 \leq i \leq n)\)的值 同时在读入的时候顺便处理处任意两个奶酪之间的距离 下面是状态转移方程 for(int i=1;i<(1<<n);i++){ for(int j=1;j<=n;j++){ if((i&(1<<…
为啥我去年这么菜啊..... 我现在想了$20min$后打了$10min$就过了$qwq$. 我们用$f[i][j]$表示当前深度为$i$,访问了状态$j$中的所有点的最小代价. 显然$f[i][j]=min(f[i-1][k]+i\times get(k,j^k)) $其中$k$为$j$的子集,$get(x,y)$表示点集$y$中所有点分别向点集$x$连边的最小代价. 显然这个dp的时间复杂度是$O(3^n\times n^2)$的. 考虑到n非常小,然后就过了. 然而我当年不会枚举子集,甚至…
题目大意:比较复杂,点 这里 看题. 题解:对于状态压缩 dp 来讲,阶段的确立十分重要.本题中,采用以层次为阶段进行状压 dp. 设状态 \(f[i][S]\) 表示开凿到深度 \(i\),当前已经打通的点集为 \(S\) 时的最小花费. 则状态转移方程为 \[f[i][S]=min\{f[i-1][S']+(i-1)*cost(S',S) \}\] 因此,预处理出状态转移之间的花费和对于每个状态而言,可行的状态即可. 时间复杂度为 \(O(n*3^n)\). 代码如下 #include <b…
\(Sol\) 觉得这里是个很巧妙的地方吖,就是记下当前扩展点集的最大深度,然后强制下一步扩展的点集都是最大深度+1.这样做在当前看可能会导致误算答案导致答案偏大,但是整个\(dp\)完成后一定可以得到最优解. 怎么计算扩展点集的代价呢,显然是要扩展的点向已扩展的点里连最短边,这个可以暴力计算. 注意一个细节就是输入可能有重复的边,取边权最小的即可.图论题都要注意这一点! \(Code\) #include<bits/stdc++.h> #define il inline #define Ri…
原文链接https://www.cnblogs.com/zhouzhendong/p/9261079.html 题目传送门 - 洛谷P3959 题目传送门 - Vijos P2032 题意 给定一个 $n$ 个节点 $m$ 条边的无向图. 现在请你在这个图之上生成一个有根树. 记 $d_i$ 为节点 $i$ 的深度 $(d_{root}=0)$ ,记 $fadis_i$ 为节点 $i$ 到其父亲节点的连边中的最小边权. 则这棵树的代价为 $$\sum_{i=1}^{n}(d_i\times fa…
一:状压dp的基本特征 状态压缩问题一般是指用十进制的数来表示二进制下的状态 这种用一个数来表示一组数,以降低表示状态所需的维数的解题手段,就叫做状态压缩. 常用到位运算 二:位运算 &:与运算,相同为1不同为0 | :或运算,全0位0,否则为1 ^:异或运算,不同为1,相同为0(也叫半加与运算) <<:左移操作,x<<j,x在二进制下向左移j位,(也就是原来的数乘j即:x*=j)右边用0填充,反码不同,要用1填充(负数) >>:右移操作,x>>j相…
$11*11$格子板上铺$1*2$地砖方案.以前做过?权当复习算了,毕竟以前学都是浅尝辄止的..常规题,注意两个条件:上一行铺竖着的则这一行同一位一定要铺上竖的,这一行单独铺横的要求枚举集合中出现连续偶数个的1,预处理一下即可.注意数据及时reset. #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include…
Painful Bases LightOJ - 1021 这个题目一开始看,感觉有点像数位dp,但是因为是最多有16进制,因为限制了每一个数字都不同最多就有16个数. 所以可以用状压dp,看网上题解是 dp[s][r] 表示数字集合为s,对 k 取余为r的方案数. 这个题目首先把给你的字符转化成数字,然后枚举状态,枚举模数,枚举每一位的所有可能. 这个注意是写离散化的,不是直接暴力,虽然理论上都会超时,但是实际上离散化的没有超时. 这个题目我觉得还挺好的,以后可以在写写 #include <io…
洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层有关,所以如果我们能够将一层的边一起加进去,计算就会方便许多.于是想办法把这个转移过程状压一下. 设\(f_{i,j}\)为当前已选点集为\(i\),下一层加入的点集为\(j\)时,新加入的所有点与原有点之间最小的边权之和.计算的具体实现,我们\(O(2^n)\)枚举\(i\),再枚举\(i\)的补…
题目:https://www.luogu.org/problemnew/show/P3959 原来写了个不枚举起点的状压dp. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; ,M=(<<)+,INF=0x3f3f3f3f; int n,m,lm,b[N][N],d…
传送门 为什么感觉状压dp都好玄学……FlashHu大佬太强啦…… 设$f_{i,j}$表示当前选的点集为$i$,下一次要加入的点集为$j$时,新加入的点和原有的点之间的最小边权.具体的转移可以枚举$i$,然后枚举$i$的补集$j$,找出$j$的$lowbit_j$ 那么转移就是$$f_{i,j}=min\{f_{i,j-lowbit_j}+min\{dis[lowbit_j][i]\}\}$$ 据说这一部分的复杂度是$O(3^nn)$,因为$n$元素的所有子集的大小之和是$3^n$(然而我并不…
一开始状态设计错了-- 设f[i][s]为当前与根节点联通状况为s,最深深度为i 转移的话枚举当前没有和根联通的点集,预处理出把这些点加进联通块的代价(枚举s中的点和当前点的连边乘以i即可),然后用没联通点的集合b去更新f[i+1][s|b]即可 位运算处理用类似lowbit的东西 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=15; int…
题目描述: 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多. 小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某 个宝藏屋的通道,通往哪个宝藏屋则由小明来决定. 在此基础上,小明还需要考虑如何开凿宝藏屋之间的道路.…
题面 传送门:https://www.luogu.org/problemnew/show/P3959 Solution 这道题的是一道很巧妙的状压DP题. 首先,看到数据范围,应该状压DP没错了. 根据我们之前状压方程的设计经验,我们很快就能设计出这样的方程: 设f[i][j]表示用到第i个元素,当前连接状态为j的开销的min 但是我们很快就会发现,这个方程没法转移,因为随着连接方案的不同,新插入的点的K值会不同. 怎么办呢? 这时候我们可以重新设计一个巧妙的的状态. 重新阅读题目,我们可以发现…
https://www.luogu.org/problemnew/show/P3959 考场上我怎么想不出来这么写的,状压白学了. 直接按层次存因为如果某个点在前面存过了则肯定结果更优所以不用在意各点的层次只用在意最深的点的层次. 调的时候因为e最开始初始化太大了溢出了好几次mdzz. #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<c…