题解 P5798 【[SEERC2019]Level Up】
简单 dp。
考虑定义
重要的是做任务的顺序不同,我们的答案也不同。因为一级溢出的经验会给二级,所以我们理性猜测一级能够得到的经验更多的任务放在后面。也就是把读入的任务以
问题解决了!
注意卡空间要开滚动数组。不要开大可能会 T。一定要开 O2,太慢了。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF=0x3f3f3f3f3f3f3f3f;
LL now;
#define Nxt (now^1)
struct task{
LL x,t,y,r;
bool operator < (task another) const {return x<another.x;}
}p[505];
LL n,s1,s2,dp[2][505][505];
int main(){
scanf("%lld %lld %lld",&n,&s1,&s2);
for(LL i=1;i<=n;++i) scanf("%lld %lld %lld %lld",&p[i].x,&p[i].t,&p[i].y,&p[i].r);
sort(p+1,p+1+n);
memset(dp,0x3f,sizeof dp);//气气气这里不要用 127,memset 太慢了
dp[0][0][0]=0;
for(LL i=1;i<=n;++i)
{
memcpy(dp[Nxt],dp[now],sizeof dp[now]);//滚动数组将当前状态放上去。
for(LL j=0;j<=s1;++j)
{
for(LL k=0;k<=s2;++k)
{
if(dp[now][j][k]!=INF)
{
if(j<s1)
{
LL level1=j+p[i].x;
if(level1>s1)
{
LL overflow=level1-s1+k;
overflow=min(overflow,s2);
dp[Nxt][s1][overflow]=min(dp[Nxt][s1][overflow],dp[now][j][k]+p[i].t);
}
else dp[Nxt][level1][k]=min(dp[Nxt][level1][k],dp[now][j][k]+p[i].t);
}//将经验放在第一级,分情况讨论溢出到第二级和不溢出。
LL level2=k+p[i].y;
level2=min(level2,s2);
dp[Nxt][j][level2]=min(dp[Nxt][j][level2],dp[now][j][k]+p[i].r); //放在第二级
}
}
}
now^=1;
}
printf("%lld",(dp[now][s1][s2]==INF || !dp[now][s1][s2])?-1:dp[now][s1][s2]);//能达到满级吗
return 0;
}