5月16日总结
Posted 偶尔爆零的蒟蒻
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5月16日总结相关的知识,希望对你有一定的参考价值。
背包总结
01背包问题:N个物品,每个物品只有1件,每个物品价值为Vi,体积为Wi,容量为M的背包最多装多少价值的物品。
d p [ i ] 表 示 容 量 为 i 时 , 最 多 装 多 少 价 值 dp[i]表示容量为i时,最多装多少价值 dp[i]表示容量为i时,最多装多少价值
f o r i ( 1 , n ) for\\ \\ \\ \\ \\ i(1,n) for i(1,n)
f o r j ( V , w [ i ] ) for\\ \\ \\ \\ \\ j(V,w[i]) for j(V,w[i])
d p [ j ] = m a x ( d p [ j ] , d p [ j − w [ i ] ] + v [ i ] ) dp[j]=max(dp[j],dp[j-w[i]]+v[i]) dp[j]=max(dp[j],dp[j−w[i]]+v[i])
第 二 层 循 环 必 须 从 V 到 w [ i ] : 每 个 物 品 只 有 一 件 , 不 会 导 致 同 一 件 物 品 多 次 使 用 第二层循环必须从V到w[i]:每个物品只有一件,不会导致同一件物品多次使用 第二层循环必须从V到w[i]:每个物品只有一件,不会导致同一件物品多次使用
如 果 循 环 从 w [ i ] 到 V , 则 当 j = 2 ∗ w [ i ] 时 如果循环从w[i]到V,则当j=2*w[i]时 如果循环从w[i]到V,则当j=2∗w[i]时
d p [ j − w [ i ] ] = v [ i ] , d p [ j ] = d p [ j − w [ i ] ] + v [ i ] = 2 ∗ v [ i ] , 放 了 2 次 dp[j-w[i]]=v[i],dp[j]=dp[j-w[i]]+v[i]=2*v[i],放了2次 dp[j−w[i]]=v[i],dp[j]=dp[j−w[i]]+v[i]=2∗v[i],放了2次
当 j 远 大 于 w [ i ] 时 , 第 i 件 物 品 会 被 多 次 使 用 , 变 成 完 全 背 包 问 题 当j远大于w[i]时,第i件物品会被多次使用,变成完全背包问题 当j远大于w[i]时,第i件物品会被多次使用,变成完全背包问题
所 以 , 01 背 包 和 完 全 背 包 的 一 维 D P , 第 二 层 循 环 方 向 相 反 所以,01背包和完全背包的一维DP,第二层循环方向相反 所以,01背包和完全背包的一维DP,第二层循环方向相反
如 果 初 始 化 d p [ 0 ] = 0 , d p [ 1... j ] = − i n f 如果初始化dp[0]=0,dp[1 ... j]=-inf 如果初始化dp[0]=0,dp[1...j]=−inf
则 d p [ i ] 是 恰 好 容 量 为 i 时 的 背 包 最 大 价 值 , 如 果 不 能 恰 好 装 满 , 就 是 负 数 则dp[i]是恰好容量为i时的背包最大价值,如果不能恰好装满,就是负数 则dp[i]是恰好容量为i时的背包最大价值,如果不能恰好装满,就是负数
因 为 当 容 量 溢 出 时 , d p [ j − w [ i ] ] 为 负 数 , 就 像 是 搭 建 空 中 楼 阁 , 因为当容量溢出时,dp[j-w[i]]为负数,就像是搭建空中楼阁, 因为当容量溢出时,dp[j−w[i]]为负数,就像是搭建空中楼阁,
只 能 在 之 前 已 有 的 基 础 上 更 新 数 据 , 否 则 数 据 无 效 只能在之前已有的基础上更新数据,否则数据无效 只能在之前已有的基础上更新数据,否则数据无效
完全背包:N个物品,每个物品有无数件,每个物品价值为Vi,体积为Wi,容量为M的背包最多装多少价值的物品。
f o r i ( 1 , n ) for\\ \\ \\ \\ \\ i(1,n) for i(1,n)
f o r j ( w [ i ] , V ) for\\ \\ \\ \\ \\ j(w[i],V) for j(w[i],V)
d p [ j ] = m a x ( d p [ j ] , d p [ j − w [ i ] ] + v [ i ] ) dp[j]=max(dp[j],dp[j-w[i]]+v[i]) dp[j]=max(dp[j],dp[j−w[i]]+v[i])
多重背包:N个物品,每个物品有Si件,每个物品价值为Vi,体积为Wi,容量为M的背包最多装多少价值的物品。
可拆成01背包
f o r i ( 1 , n ) for\\ \\ \\ \\ \\ i(1,n) for i(1,n)
f o r k ( 1 , s [ i ] ) for\\ \\ \\ \\ \\ k(1,s[i]) for k(1,s[i])
f o r j ( V , w [ i ] ) for\\ \\ \\ \\ \\ j(V,w[i]) for j(V,w[i])
d p [ j ] = m a x ( d p [ j ] , d p [ j − w [ i ] ] + v [ i ] ) dp[j]=max(dp[j],dp[j-w[i]]+v[i]) dp[j]=max(dp[j],dp[j−w[i]]+v[i])
二进制优化
for (int i = 1; i <= n; i++) {
int num = min(p[i], V / w[i]);
for (int k = 1; num > 0; k <<= 1) {
if (k > num) k = num;
num -= k;
for (int j = V; j >= w[i] * k; j--)
f[j] = max(f[j], f[j - w[i] * k] + v[i] * k);
}
分组背包:N个物品,一共K组,每组有若干件,每组只能取一个,每个物品价值Vi,体积Wi,容量为M的背包最多装多少价值的物品。
f o r p ( 1 , k ) / / k 组 for\\ \\ \\ \\ \\ p(1,k)//k组 for p(1,k)//k组
f o r j ( V , 0 ) for\\ \\ \\ \\ \\ j(V,0) for j(V,0)
f o r i ( ) / / 组 内 物 品 个 数 for\\ \\ \\ \\ \\ i()//组内物品个数 for i()//组内物品个数
d p [ j ] = m a x ( d p [ j ] , d p [ j − w [ i ] ] + v [ i ] ) dp[j]=max(dp[j],dp[j-w[i]]+v[i]) dp[j]=max(dp[j],dp[j−w[i]]+v[i])
状态压缩:当物品数N<=30,将长度为N的二进制串用0、1表示第i件物品取或不取。
对第i件物品,通过移位运算,与二进制状态相与, a & ( 1 < < i ) a\\&(1<<i) a&(1<<i),来确定该物品是否在该状态内
状态合并 a ∣ b a|b a∣b
集合差运算 a − b = a − a & b a-b=a-a\\&b a−b=a−a&b
判断是否有交集 a & b a\\&b a&b
状态 s s s的非空真子集 i i i
f o r ( i = s & ( s − 1 ) ; i ; i =以上是关于5月16日总结的主要内容,如果未能解决你的问题,请参考以下文章