P1156 垃圾陷阱
Posted garen-wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1156 垃圾陷阱相关的知识,希望对你有一定的参考价值。
我是真的不知道。。。
这道题对于每一个垃圾有两个决策:堆放不吃 或者 吃掉不堆放。
终止条件是堆放的高度达到(d)。想要求达到状态的最大生命值或者最久能活到多久。
可以联想到背包问题,而且是01背包。
把生命值当做价值,把高度当做重量,我们就可以用最小重量取出最大价值。
设(dp[i][j])为前(i)个垃圾,已经堆放了高度(j)的最大生命值。
递推就可以想普通的填表法搞出来。
这个东西挺奇怪的,奶牛生命值为0的时候还能转移。。。这个注意一下。
如果填表的时候填到(j==n)的时候就可以判断是可以出去的,直接return掉。
否则要输出奶牛能活最久多长时间。我们可以利用dp数组,求出的最大生命值加上那一块掉落时间。
注意:在做dp的时候,有的dp是没有状态的,是会死的。这些死的dp值是负数。
所以我们要初始化dp数组为负无穷大。
注意:给你的垃圾顺序可能是乱序的,要按照时间顺序排序。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn = 105;
const int INF = 0x3f3f3f3f;
int d, g;
struct Trash
{
int tim, t, h;
} s[maxn];
int dp[maxn][maxn];
// 前i件垃圾,堆了高度j的最大生命值
int read()
{
int ans = 0, s = 1;
char ch = getchar();
while(ch > ‘9‘ || ch < ‘0‘)
{
if(ch == ‘-‘) s = -1;
ch = getchar();
}
while(ch >= ‘0‘ && ch <= ‘9‘) ans = (ans << 3) + (ans << 1) + ch - ‘0‘, ch = getchar();
return s * ans;
}
bool cmp(const Trash a, const Trash b)
{
return a.tim < b.tim;
}
int main()
{
d = read(), g = read();
for(int i = 1; i <= g; i++)
{
s[i].tim = read(), s[i].t = read(), s[i].h = read();
}
for(int i = 0; i <= g; i++) for(int j = 0; j <= d; j++) dp[i][j] = -INF;
std::sort(s + 1, s + g + 1, cmp);
dp[0][0] = 10;
for(int i = 1; i <= g; i++)
{
for(int j = 0; j <= d; j++)
{
if(dp[i - 1][j] - (s[i].tim - s[i - 1].tim) >= 0)// 没被饿死
{
dp[i][j] = std::max(dp[i][j], dp[i - 1][j] - (s[i].tim - s[i - 1].tim) + s[i].t);
}
if(dp[i - 1][j - s[i].h] - (s[i].tim - s[i - 1].tim) >= 0 && j - s[i].h >= 0)// 没被饿死,并且能转移
{
dp[i][j] = std::max(dp[i][j], dp[i - 1][j - s[i].h] - (s[i].tim - s[i - 1].tim));
if(j == d)
{
printf("%d
", s[i].tim);
return 0;
}
}
}
}
int ans = -INF;
for(int i = 1; i <= g; i++)
{
for(int j = 0; j <= d; j++)
{
if(dp[i][j] < 0) continue;
ans = std::max(ans, dp[i][j] + s[i].tim);
}
}
printf("%d
", ans);
return 0;
}
以上是关于P1156 垃圾陷阱的主要内容,如果未能解决你的问题,请参考以下文章