考試的時候沉迷T4而忽略掉的DP題
也是該複習DP了……
摸魚:
設dp[i][j]爲第i個物品在時間爲j時的最大高度
轉移更直觀一些
dp[i][j] = dp[i - 1][j - l[i].t];//吃
dp[i][j] = dp[i - 1][j] + l[i].h//堆
注意在吃的時候,需要滿足j - l[i].t >= l[i].f,堆得話需滿足j >= l[i].f
意義爲在使用了i - 1堆垃圾而到達第i堆垃圾扔下的時間的情況,這樣纔是合法的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 20000 + 50;
struct edge{
int f,t,h;
}l[MAXN << 1];
int D,G,dp[105][MAXN],lim;
bool cmp(edge a,edge b){
return a.f < b.f;
}
int main(){
scanf("%d%d",&D,&G);
for(int i = 1;i <= G;i ++){
scanf("%d%d%d",&l[i].f,&l[i].t,&l[i].h);
}
sort(l + 1,l + G + 1,cmp);
memset(dp,-1,sizeof(dp));
for(int i = 0;i <= 10;i ++){
dp[0][i] = 0;
}
lim = 10;
for(int i = 1;i <= G;i ++){
if(lim < l[i].f){
printf("%d",lim);
return 0;
}
lim += l[i].t;
for(int j = 0;j <= lim;j ++){
dp[i][j] = dp[i - 1][j];
if(j >= l[i].f){
if(j - l[i].t >= l[i].f)dp[i][j] = max(dp[i][j],dp[i - 1][j - l[i].t]);
if(dp[i - 1][j] != -1)
dp[i][j] = max(dp[i][j],dp[i - 1][j] + l[i].h);
if(dp[i][j] >= D){
printf("%d\n",l[i].f);
return 0;
}
}
}
}
/*for(int i = 1;i <= G;i ++){
for(int j = 0;j <= lim;j ++){
printf("%d ",dp[i][j]);
}
printf("\n");
}*/
printf("%d",lim);
return 0;
}
正解:
如果不看題解是沒有這種思路的……
充分體現了DP的另一個技巧:設計不出方程的時候把數組下標和它存的內容換一換
設f[j]爲到達高度i時的最大生命時間
對於垃圾i,有吃和堆的情況:
f[j + l[i].h] = max(f[j + l[i].h],f[j]);//堆,高度增時間不增
f[j] += l[i].w //吃,吃掉時一定爲這一高度的最優情況
關於垃圾到達時間的限制,僅當f[j] >= 垃圾i的到達時間時,纔可以選擇堆或吃
否則爲i之前的垃圾無法在i到來的時刻堆到高度j,該高度不合法。
如果無法到達則全部吃掉可存活最長時間,輸出f[0]
確實有點像帶限制的01揹包?
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int D,n;
struct edge{
int f,h,w;
}l[23333];
int f[233333];
int solve(){
f[0] = 10;
for(int i = 1;i <= n;i ++){
for(int j = D;j >= 0;j --){
if(l[i].f <= f[j]){
f[j + l[i].h] = max(f[j + l[i].h],f[j]);
if(j + l[i].h >= D)return l[i].f;
f[j] += l[i].w;
}
}
}
return -1;
}
bool cmp(edge a,edge b){
return a.f < b.f;
}
int main(){
scanf("%d%d",&D,&n);
for(int i = 1;i <= n;i ++){
scanf("%d%d%d",&l[i].f,&l[i].w,&l[i].h);
}
sort(l + 1,l + n + 1,cmp);
int temp = solve();
if(temp == -1)temp = f[0];
printf("%d",temp);
return 0;
}