DP 学习
第一道题 luoguP1270
直接看题可以看出这是一道关于树的题
我们因为在学DP所以这是一道树形DP 根据题目要在给定时间内求出最大可得价值(偷最多的画)
我们考虑是否可以分出子问题,子问题如何求解,子问题如何转移
也就是要尝试用DP求解
用 f[i][j] 去表示在i点下用j时间可获得的最大价值
我们考虑转移
- 对于叶子节点 我们取最小的可拿的画与已有的画
- 对于非叶子节点 我们要分配给左右儿子时间,取最大值
这题的读入较麻烦,我们写一个dfs()去读入
顺便建成一棵树
然后遍历转移
最后的答案为f[1][n]
/***********************************************************
> File Name: LGP1270.cpp
> Author: lan_m
> QQ: 2867930696
> Created Time: 2021/9/10 7:41:59
> Modified Time:2021/9/10 7:41:59
> fighting for night
*******************************************************/
#include <bits/stdc++.h>
using namespace std;
const int N = 150;
int n;
int tot;
int tim[N];
int val[N];
void dfs(int x) {
scanf("%d%d",&tim[x],&val[x]);
tim[x] *= 2;
if(val[x] == 0) {
dfs(x<<1);dfs(x<<1|1);
}
return ;
}
int f[150][620];
void deal(int x,int sum) {
if(f[x][sum] > 0 || sum == 0) return ;
if(val[x]) {
f[x][sum] = min(val[x],(sum - tim[x])/5);
return;
}
for (int i = 0;i <= sum - tim[x];i ++) {
deal(x<<1,i);
deal(x<<1|1,sum - i - tim[x]);
f[x][sum] = max(f[x][sum],f[x<<1][i] + f[x<<1|1][sum - i - tim[x]]);
}
}
int main(){
scanf("%d",&n);n --;
dfs(1);
deal(1,n);
printf("%d",f[1][n]);
return 0;
}
另一道题luoguP3360
我们瞄一眼题,可以看出和上一题区别。
只加了偷价值为W的画用了C秒 这是一个背包,所以我们要在上一个代码中加点东西
除读入外,我们还要在叶子结点上做一个背包
/***********************************************************
> File Name: LGP3360.cpp
> Author: lan_m
> QQ: 2867930696
> Created Time: 2021/9/10 9:03:49
> Modified Time:2021/9/10 9:03:49
> fighting for night
*******************************************************/
#include <bits/stdc++.h>
using namespace std;
const int N = 600;
int n;
int tot;
int tim[N];
int val[N];
inline void read(int &x){
char ch=getchar();bool t=0;
for (;!isdigit(ch);ch=getchar())if(ch == '-')t = 1;
for (x=0;isdigit(ch);ch=getchar())x = x * 10 + ch - '0';
if(t)x=-x;
}
struct node{
int w,c;
}tp[N][40];
void init(int x){
read(tim[x]);tim[x]<<=1;
read(val[x]);
if( val[x] == 0 ){
init(x<<1);init(x<<1|1);
}
else {
for(int i = 1;i <= val[x];i ++) {
read(tp[x][i].w);
read(tp[x][i].c);
}
}
return ;
}
int f[N][N];
int f2[N];
void dfs(int x,int ttt) {
if(ttt == 0 || f[x][ttt]) return ;
if( val[x] == 0 ){
for (int i = 0;i <= ttt - tim[x];i ++) {
dfs(x<<1,i);
dfs(x<<1|1,ttt - tim[x] - i);
f[x][ttt] = max(f[x<<1][i] + f[x<<1|1][ttt-tim[x] - i] , f[x][ttt]);
}
}
else {
// 背包 ------------------------------
memset(f2,0,sizeof(f2));
for (int i = 1;i <= val[x];i ++) {
for (int j = ttt - tim[x];j >= tp[x][i].c;j --) {
f2[j] = max(f2[j] , f2[j - tp[x][i].c] + tp[x][i].w);
}
}
// ------------------------------------
f[x][ttt] = f2[ttt - tim[x]];
}
}
int main() {
read(n);n --;
init(1);
dfs(1,n);
printf("%d",f[1][n]);
return 0;
}