题解 P2871 【[USACO07DEC]手链Charm Bracelet】
dalao请无视本篇垃圾题解
好久不做DP题了,拿一道经典的01背包来找找手感【01背包直接背代码的我~笑】
显然01背包的状态转移方程是:
for(int i=1;i<=n;i++)
for(int v=V;v>=c[i];v--)
f[v]=max(f[v],f[v-c[i]]+w[i]);
那么问题来了
为什么第二层循环是从V开始的?
其实原来我也不太明白,只是半知半解,今天才突然明白,果然我是最弱的QAQ
答:
从动态规划的基本思想来看,就是将体积为V的背包拆分为体积为Vi的背包,通过求每一种体积的01背包的最优解来构成目标体积的01背包的最优解的最优子结构
用通俗的语言来说就是:
设:当前背包内剩余的容量为v。
那么 f[v-c[i]]+w[i]即为装入体积为c[i]的物品,剩余容量-c[i],获得的价值是w[i]
不妨我们枚举每一种Vi【信竞对数学的笑容:)】,从而获得第i种物品在容量为Vi的01背包中的最优状态(选或不选)由此我们便获得了最优子结构
为什么第一层循环是i?
反证法:
假设第一层循环是v
若当前有wi+wi>wj,那么我们就会选择两个i号物品,所以,枚举物品i需要在第一层循环进行
下面就是你们最爱的AC代码了OvO
#include<bits/stdc++.h>
#define maxn 23333
using namespace std;
int n,V;
int c[maxn],w[maxn],f[maxn];
int main()
{
cin>>n>>V;
for(int i=1;i<=n;i++)cin>>c[i]>>w[i];
for(int i=1;i<=n;i++)
for(int v=V;v>=c[i];v--)
{
f[v]=max(f[v],f[v-c[i]]+w[i]);
}
cout<<f[V];
return 0;
}