## 1.01背包基础

https://www.acwing.com/problem/content/description/2/

dp[i][j]表示当容量为j的时候前i个物品的最大价值是什么？

dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i])

``````#include<iostream>
using namespace std;
#define N 1001
int v[N];
int w[N];
int f[N][N];
int main()
{
int n,m;
cin >> n >> m;
for(int i = 1;i <= n;i++){
cin >> v[i] >> w[i];
}
for(int i = 1;i <= n;i++){
for(int j = 0;j <= m;j++){
f[i][j] = f[i - 1][j];
if(v[i] <= j) f[i][j] = max(f[i][j],f[i - 1][j - v[i]] + w[i]);
}
}
cout << f[n][m];
return 0;
}``````

``````#include<iostream>
using namespace std;
int main()
{
int n, v;
cin >> n >> v;
int cap[n + 1] = {0};
int val[n + 1]= {0};
for(int i = 1; i <= n; i++) {
cin >> cap[i] >> val[i];
}
int dp[v + 1] = {0};
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= v; j++) {
if(j - cap[i] >= 0)
dp[j] = max(dp[j], dp[j - cap[i]] + val[i]);
}
}
cout << dp[v] << endl;
return 0;
}``````

``````#include<iostream>
using namespace std;
int main()
{
int n, v;
cin >> n >> v;
int cap[n + 1] = {0};
int val[n + 1]= {0};
for(int i = 1; i <= n; i++) {
cin >> cap[i] >> val[i];
}
int dp[v + 1] = {0};
for(int i = 1; i <= n; i++) {
for(int j = v; j >=0; j--) {
if(j - cap[i] >= 0)
dp[j] = max(dp[j], dp[j - cap[i]] + val[i]);
}
}
cout << dp[v] << endl;
return 0;
}``````

``````for(int j = v; j >= cap[i]; j--)
dp[j] = max(dp[j], dp[j - cap[i] + val[i]);``````

## 01背包的变体例题

``````import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int money = sc.nextInt() / 10;
int m = sc.nextInt();
int[][] w = new int[m + 1][3];
int[][] v = new int[m + 1][3];
int id = 1;
int[][] pre = new int[m][3];
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < m; i++) {
int price = sc.nextInt() / 10;
int imp = sc.nextInt();
int states = sc.nextInt();
pre[i][0] = price;
pre[i][1] = imp;
pre[i][2] = states;
if(states == 0) {
w[id][0] = price;
v[id][0] = price * imp;
map.put(i, id);
id++;
}
}
for(int i = 0; i < m; i++) {
int states = pre[i][2];
if(states == 0)
continue;
int price = pre[i][0];
int imp = pre[i][1];
int idx = map.get(states - 1);
if(w[idx][1] == 0) {
w[idx][1] = price;
v[idx][1] = imp * price;
} else {
w[idx][2] = price;
v[idx][2] = imp * price;
}
}
int[] dp = new int[money + 1];
for(int i = 1; i <= id; i++) {
for(int j = money; j >= 1; j--) {
int t = dp[j]; //不买
if(j >= w[i][0]) t = Math.max(t, dp[j - w[i][0]] + v[i][0]); //买主
if(j >= w[i][0] + w[i][1]) t = Math.max(t, dp[j - w[i][0] - w[i][1]] + v[i][0] + v[i][1]); //主1
if(j >= w[i][0] + w[i][2]) t = Math.max(t, dp[j - w[i][0] - w[i][2]] + v[i][0] + v[i][2]); //主2
if(j >= w[i][0] + w[i][1] + w[i][2]) t = Math.max(t, dp[j - w[i][0] - w[i][1] - w[i][2]] + v[i][0] + v[i][1] + v[i][2]);
dp[j] = t;
}
}
System.out.println(dp[money] * 10);
}
}``````

## 完全背包问题

https://oj.youdao.com/problem/725

``````#include<iostream>
using namespace std;
int main()
{
int m, n;
cin >> m >> n;
int w[n + 1] = {0};
int v[n + 1] = {0};
int dp[m + 1] = {0};
for(int i = 1; i <= n; i++) {
cin >> w[i] >> v[i];
}
for(int i = 1; i <= n; i++) {
for(int j = w[i]; j <= m; j++) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
cout << "max=" << dp[m] << endl;
return 0;
}``````

https://leetcode.cn/problems/coin-change-ii/

``````class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount + 1);
dp[0] = 1;
for(int t: coins) {
for(int i = t; i <= amount; i++) {
dp[i] += dp[i - t];
}
}
return dp[amount];
}
};``````

https://leetcode.cn/problems/coin-change/

``````int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount + 1, 10000000);
dp[0] = 0;
for(int coin: coins) {
if(coin > amount) continue;
dp[coin] = 1;
for(int j = coin + 1; j <= amount; j++) {
dp[j] = min(dp[j - coin] + 1, dp[j]);
}
print(dp);
}

return dp[amount] == 10000000 ? -1 : dp[amount];
}
int print(vector<int> &dp) {
for(int d: dp)
cout << d << " ";
cout << endl;
return 0;
}``````

``````0 1 2 3 4 5 6 7 8 9 10 11
0 1 1 2 2 3 3 4 4 5 5 6
0 1 1 2 2 1 2 2 3 3 2 3``````

https://leetcode.cn/problems/combination-sum-iv/

``````class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<int> dp(target + 1);
dp[0] = 1;
for(int i = 1; i <= target; i++) {
for(int n: nums) {
if(i >= n && dp[i] < INT_MAX - dp[i - n]) dp[i] += dp[i - n];
}
}
return dp[target];
}
};``````