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

int main() {
    int totalWeight, type;
    while (cin >> totalWeight >> type) {

        int value[type], weight[type];
        for (int i = 0; i < type; i++) 
            cin >> weight[i] >> value[i];

        //构造dp数组
        int dp[type + 1][totalWeight + 1];

        for (int i = 0; i <= type; i++) {
            for (int j = 0; j <= totalWeight; j++) {
                if (i * j == 0) {
                    dp[i][j] = 0;//0容量的背包、或0价值的物品总价值为0
                } else { //物品有价值,或者背包有容量
                    //物品放不下时
                    if (weight[i-1] > j) {
                        dp[i][j] = dp[i-1][j];
                    } else { //放得下时,两者取大
                        dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i-1]]+value[i-1]);
                    }
                }
            }
        }
        //输出dp中最大值
        int max = INT_MIN;
        for (int i = 0; i <= type; i++) {
            for (int j = 0; j <= totalWeight; j++) {
                if(dp[i][j]>max)
                    max = dp[i][j];
            }
        }
        cout<<max<<endl;
    }
}
// 64 位输出请用 printf("%lld")

经典01背包,分析一下状态转移方程:

如果背包容量为0/物品价值、重量为0,则总价值为0:dp[i][j] = 0

如果当前物品放不进背包,则总价值与不放该物品时的最大价值(即二维数组的上一行)一样,即:dp[i][j] = dp[i-1][j]

如果当前物品可以放进背包,则总价值看放进背包后价值是否上涨,是则放入,即:dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i-1]]+value[i-1])