01背包:
一维数组dp方程
for(int j = n; j >= w[i];j--){
dp[j] = dp[j - w[i] ] +v[i];
}
多重背包:
1:将一个有x份物品的拆成x一份的物品,循环数倍扩大,时间复杂度受不了
2:二进制优化:原理:将一个数x用二进制表示后,每一位的0或1可表示1-x的所有数
int num = 0;
for (int i = 1; i <= m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
for (int j = 1; j <= c; j <<= 1) {
pri[++num] = a * j;
wei[num] = b * j;
c -= j;
if (c) {
pri[++num] = a * c;
wei[num] = b * c;
}
}
}
完全背包:
一维dp方程:
for(int j = w[i]; j <= n;j++){
dp[j] = dp[j - w[i] ] +v[i];
}
与01背包循环顺序相反
一个难题
Partial Tree
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX_N = 2e5;
int f[MAX_N];
int dp[MAX_N];
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(dp,-INF,sizeof(dp));
int n;
scanf("%d",&n);
for(int i = 1;i < n; i++){
scanf("%d",&f[i]);
}
int ans = f[1] * n;
int num = n - 2;
dp[0] = 0;
for(int i = 1;i <= n - 2; i++) {
for(int j = 1; j <= num; j++){
if(j >= i)
dp[j] = max(dp[j], dp[j - i] + f[i + 1] - f[1]);
}
}
printf("%d\n",ans + dp[num]);
}
return 0;
}