dp-01背包

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
第 i 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式
输出一个整数,表示最大价值。

数据范围
0<N,V≤1000
0<vi,wi≤1000

输入样例
4 5
1 2
2 4
3 4
4 5
输出样例
8

以AcWing上的这道题来讲解这个问题,其实这个背包问题的思路就是打表,i表示第i个物体,j表示体积。i为列标,j为横标。
对于每个物体,我们都让j从1递增到V并判断是否能放下,如果不能放下,直接用dp[i-1][j]替代即可,否则,按照最大价值的原则来考虑的话,dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i])
如果不懂得话可以这么考虑:在j取的每一次值都对n个物体进行判断能不能放,如果第i个物体不能放,那么dp[i][j]=他之前的情况,也就是dp[i-1][j];如果可以放,则考虑放进去他的价值大还是不放他的价值大。可能会有人说:“肯定是放他的价值大啊”。其实不一定的,这里如果要放的话,价值就不是dp[i-1][j]+w[i]了而是dp[i-1][j-v[i]]+w[i]。因为在容量为j的情况下装上第i个物体还可能有剩余的空间,所以还要算上这个剩余的空间能装的物体的价值,也就是dp[i-1][j-w[i]]+w[i];
这里有图解

代码:


 #include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
using namespace std;

int N,V;
int dp[1005][1005],v[1005],w[1005];

int main(void)
{
        cin>>N>>V;
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=N;i++)
            cin>>v[i]>>w[i];
        for(int i=1;i<=N;i++)
        {
            for(int j=1;j<=V;j++)
            {
                if(j<v[i])
                    dp[i][j]=dp[i-1][j];
                else
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
            }
        }
        cout<<dp[N][V]<<endl;//直接将最后一个单元输出即可
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_42891420/article/details/88084751