题解 P1156 【垃圾陷阱】
很显然的想到f[i][j]。
但是!翻了翻题解,发现第一页竟然没有第二维表示血量的题解,这让花了一小时处理细节的蒟蒻非常不开森!!!
so,我来发一篇,交代一下细节,传授一下大道。(炫耀一下一小时的努力成果
主要就是for循环中的两个if。
请看注释:
#include<bits/stdc++.h>
using namespace std;
int n,d;
int dp[201][20201];
struct node {
int t,f,h;
}q[201];
bool cmp(node a,node b) {
return a.t<b.t;
}
int main() {
cin>>d>>n;
for(int i=1;i<=n;i++) cin>>q[i].t>>q[i].f>>q[i].h;
sort(q+1,q+n+1,cmp);
if(q[1].t>10) { //很显然的特判,其实不加也可以。
cout<<"10";
return 0;
}
for(int i=0;i<=n;i++) for(int j=20200;j>=0;j--) dp[i][j]=-99999999; //其实j的范围没必要开这么大,但大一点比较稳。
dp[0][10]=0; //初始化
for(int i=1;i<=n;i++) {
for(int j=0;j<=3200;j++) { //此处j的循环要注意,范围是3200以上大概都可以
//但这个for循环还与上面的预处理有关联
//因为下面有调用 j+(q[i].t-q[i-1].t) ,所以 预处理时j的范围应该比此处循环的范围大1000 左右
if(j+(q[i].t-q[i-1].t)>=0&&dp[i-1][j+(q[i].t-q[i-1].t)]+q[i].h>=0) dp[i][j]=max(dp[i][j],dp[i-1][j+(q[i].t-q[i-1].t)]+q[i].h);
if(j+(q[i].t-q[i-1].t)-q[i].f>=q[i].t-q[i-1].t&&dp[i-1][j+(q[i].t-q[i-1].t)-q[i].f]>=0) dp[i][j]=max(dp[i][j],dp[i-1][j+(q[i].t-q[i-1].t)-q[i].f]);
//往上第一个if判断,f[i][j]由f[i-1][j+(q[i].t-q[i-1].t)-q[i].f]转移而来,转移时必须满足的一个条件时,转移前的血量足够支撑到转移。
//也就是 j+(q[i].t-q[i-1].t)-q[i].f (转移前) >= q[i].t-q[i-1].t
if(dp[i][j]==d&&j!=1) {
cout<<q[i].t<<endl;
return 0;
}
}
}
int tail=10;
for(int i=1;i<=n;i++) {
if(q[i].t<=tail) tail+=q[i].f;
}
cout<<tail;
}
手动模拟查错一小时,我太难了