题意:
往手镯上镶嵌宝石,手镯总重量有上限,要求手镯的总价值最大。
本质就是一个01背包问题。
解题思路:
下面开始分析01背包问题。
动态规划问题主要是找到子问题,即一旦确定了第i个状态,就可以直接推出第i+1个状态。(有后效性)
以题目给出的数据举例:
4 6 n m ① 1 4 w[i] v[i] ② 2 6 ③ 3 12 ④ 2 7
设F[j]为背包剩余容积为j时背包所能达到的最大价值。(j <= m)
取①号物体时,如果j < 1,则F[0] = 0,如果j >= 1时,F[1]=F[2]=...=F[6]=4;
取②号物体时,如果j < 2,则F[1]保持不变,仍为4;
如果j >= 2,则可以选择取或者不取②号物体,因此F[j] = max(F[j],F[ j-w[i] ]+v[i]);(如下所示)
取:F[2] = F[ j-w[i] ]+v[i] = F[0]+v[2]=0+6=6;
F[3] = F[ j-w[i] ]+v[i] = F[1]+v[2]=4+6=10;
F[4] = F[ j-w[i] ]+v[i] = F[2]+v[2]=4+6=10;...F[5]=F[6]=10;
不取:F[1]=F[2]=...=F[6]=4;
因此F[j]=max(取,不取)=max(F[j],F[ j-w[i] ]+v[i]);
取③号物体...取④号物体,依次类推
下面是代码实现:
#include <cstdio>
#include <algorithm>
using namespace std;
int w[3410],v[3410]; //记录各个物体的重量和价值
int f[12900]; //记录当背包剩余重量为j时的背包最大价值
int main()
{
int n,m;//n是个数,m是最大重量
scanf("%d%d",&n,&m);
for(int i = 0;i < n;i++)
{
scanf("%d%d",&w[i],&v[i]);
}
for(int i = 0;i < n;i++)
{
for(int j = m;j >= 1;j--)
{
if(j >= w[i])
{
f[j] = max(f[j],f[j-w[i]]+v[i]);//取还是不取
}
}
}
sort(f,f+m+1);
printf("%d\n",f[m]);
return 0;
}