1.背包问题
01背包
uva 562 - Dividing coins :
如果某个值x能够到达,那么tot-x一定能到达
只用从i=tot/2 逐渐减小 开始检查 是否i和tot-i都能到达
01背包,对一头牛的两个值a、b,一个看成花费,一个看成是价值。
这也是数组的运用dp[],一个数组其实就是一个映射。在x->dp[x]中,不仅要注意dp[x]的意义,还要充分利用x的意义。
dp[x]表示a值总和为x时,b值和的最大值。
如果花费大于0(一般的01背包),要逆序遍历。
如果花费小于0, 则要升序。
虽然总体积有负数值,我们可以按一定的规则把它存到对应的正值下标x的dp[x]下。
要求出第k大的价值,经典的背包拓展成二维,dp[v][t]表示容量为v的背包能装的第t大的价值。
状态转移类似于一个归并排序。
背包问题的dp其实有两种意义,对应不同的转移。
dp[x]既可以表示容量为x的背包对应的最大价值,(此时初始化均为0)
又可以表示装载了x体积对应的最大价值。(此时dp[0]初始化为0。其余可以为负值了 ,表示达不到。)
集合x是s的子集: s==x|s , x==x&s
集合x与s的有交集: x&s
对于集合s,求它的所有非空真子集: for(int x=(s-1)&s ; x ;x=(x-1)&s ) { }
很方便修改为子集。
01背包:每个物品只能用一次,
dp[v][i]=min( dp[v-cost][i-1]+val[i],dp[v][i])
其核心思想实质是: 分阶段动归,考虑了第i种物品的结果= 现在试加入第i物品一个,然后将其与 前i-1个物品的结果
综合考虑。
不论转移方程具体如何,其本质如此。
当前利用的结果一定是之前计算好的。对此要设计好顺序性及排序方法。
dp[v] =min( dp[v-cost]+val[i],dp[v])
完全背包
虽然网上说这是基础题,感觉其实并不简单,虽然有人将此题归为完全背包,但感觉和经典的背包转移还是有些差别。
dp[x][i]表示体积为x时的,前i种物品,能达到的方法种数。
状态转移方程:
dp[x][i] =dp[x][i-1]+dp[x-cost[i]][i];
意味对于体积为x的背包,若考虑将状态从只用了前i-1种物品,转移到用了前i种物品。
则要将原来的状态 加上 用了第i种物品时种类数。(其实在x-cost[i]时就已经证明用了第i种物品了)
可用一维数组表示。
UVA 147 - Dollars 完全背包
必须对精度作出处理。推荐其中一种精度的处理方法。
可以将5c当作1处理,节约数组空间。因为货比都是5的倍数
对于计数dp,一定要想到long long和取模。
poj 3181 大数/高精度的完全背包
大数的钱币兑换问题
zoj 3623 动态规划的无后效性 + 问题转化
zoj 3524 拓扑排序+背包
zoj 3662 分阶段动归
多重背包
混合背包(完全+多重)+上限处理
poj 2063 Investment 贪心+完全背包
贪心:只要每年的选择获利最大即可。
poj 1276 裸多重背包
hdu 1509 多重背包,超水
poj 2392 排序(贪心)+dp(背包)
总结一下,多重背包就是分解成多个0、1背包。完全背包和多重背包考得似乎比01背包多。
dp[v]的意义:有些题目是指体积v的背包能创造最大价值,(不必装满)
有的题目是指完全装满体积v,能得到的最大价值。
像钱币兑换问题,dp[v]时价值一定是v,此时可以用bool型表示dp[v]能否达到。
像钱币兑换的计数dp,dp[v]+=dp[v-cost],dp[v]表示目前凑成v价值的方法数。
使用动态规划,先要看问题的规模,
然后在关键有几个:1.是找到适当的状态能表示起点和终点。
2.是状态转移方程必须满足无后效性。(通常符合了这一点应该就可以写出状态转移方程)
3. 最优子结构,只有满足才能用dp
4. 按合理的顺序进行动态规划
其中第三点是使用dp的基础,难点在于1、2、4三点,如果考察到2,感觉2最难,2和4的联系很紧密。
个人感觉,背包模型很有用,用的时候要找到物品的“花费”和“价值”,才能对应到题目上去。
关于顺序性的设计与枚举有密切联系,枚举的层次变换了,往往代表不同的意义。
一般来说“消耗”较少,“价值”可能会较大,因为存储空间有限啊!
对于 dp[v],举个极端的情形: v就代表数量,我要从100个人中找到10个人,dp[10]代表10个人能到达的某种效果,
这里的dp[v]是指实际到达了v,而不是花费<=v。一个人的cost自然是1,
给出一个for循环 for(int v=0;v<=V;v++)
其实这样就成了分阶段的动归了。
背包的实质是分阶段动归,然而通常01背包和完全背包被省略了一维。
1.对于一般的背包问题,dp[x]往往单调递增,有时可以利用这个转化问题。