您的位置:首页 > 其它

[队内测试Day10.22T3][codevs1684]垃圾陷阱

2017-10-22 17:19 447 查看
题目←

考试的时候沉迷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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: