cin >> n >> m;
vector<int> dp(m + 1);
for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
for(int i = 1; i <= n; i ++){
    for(int j = m; j >= v[i]; j --) dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
}    
cout << dp[m] << endl;
这段代码表示的是最基础的01背包问题:n物品,每件的体积为v[i],价值为w[i];背包的容积为m,求在不超过背包容积的情况下可以装到的最大价值和
如何求第二问:恰好装到容积m时的最大价值?
最关键的是:
for(int j = m; j >= v[i]; j --) dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
即状态是由前面的一个状态转移而来,在最基础的01背包问题里面,所有的dp[i]初始化为0,表示在体积为i时可以装到的最大价值为0,所以状态可以从i = 0, i = 1, i = 2....转移而来
如果将dp[i]全部设置为-inf,表示不能从i转移,仅设置dp[0] = 0,那么所有的状态只能从i = 0转移,此时dp[m]就表示的是体积为m时装到的最大价值
区别:
在最基础的01背包里面dp[m]可以又dp[0]转移而来,使用的体积为m - 0, 也可以由dp[1]转移而来,使用的体积为m - 1,也可以由dp[2]转移而来,使用的体积为m - 2.....
将dp[i]全部设置为-inf,表示不能从i转移,仅设置dp[0] = 0,那么dp[m]只能从dp[0]转移而来,使用的体积为m,从而达到题目目的!
fill(dp.begin() + 1, dp.begin() + 1 + m, -1000000000);
dp[0] = 0; 
for(int i = 1; i <= n; i ++){
    for(int j = m; j >= v[i]; j --) dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
}
cout << max((int)0, dp[m]) << endl;
总代码:
#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;


const int N = 1e3 + 10;
int n, m;
int v[N], w[N];
signed main(){
    HelloWorld;
    
    cin >> n >> m;
    vector<int> dp(m + 1);
    for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
    for(int i = 1; i <= n; i ++){
        for(int j = m; j >= v[i]; j --) dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
    }    
    cout << dp[m] << endl;
    fill(dp.begin() + 1, dp.begin() + 1 + m, -1000000000);
    dp[0] = 0; 
    for(int i = 1; i <= n; i ++){
        for(int j = m; j >= v[i]; j --) dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
    }
    cout << max((int)0, dp[m]) << endl;
    return 0;
}