P2317 [HNOI2005] 星际贸易
Jerrywang09 · · 题解
本题的题面很复杂啊……有几个要点需要注意:经过任何一个星球,都必须要进行飞船维护;从一个星球转移到另一个,所消耗的燃料是
第一问很简单。问你最大贸易额是多少,不计一切代价!假设可以完成任务,则第一问答案直接背包即可。
第二问才是难点。数据有一个很好的性质:只有一种获得最大贸易额的方法。这启发我们倒推 DP 状态,就可以找到在哪些星球上卖货。设
1.
上面这个
-
g(i,j)\gets \max(g(i, j), g(i, j-1)+P_i)
这就是在当前星球上充能量的转移。需要保证
针对第一个转移,
令注:数据范围应该是
再次更新:题面的数据范围已经改对了。
// P2317 [HNOI2005] 星际贸易
#include <cstdio>
#include <iostream>
#include <cstring>
#define ll long long
#define rep(i, s, t) for(int i=s; i<=t; ++i)
#define debug(x) cerr<<#x<<":"<<x<<endl;
const int N=2005, M=4005, inf=0x3f3f3f3f;
using namespace std;
char buf[1<<21], *p1=buf, *p2=buf;
#define gc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
int x=0, f=1; char c=gc();
while(c<'0' || c>'9') c=='-' && (f=-1), c=gc();
while('0'<=c && c<='9') x=(x<<3)+(x<<1)+c-'0', c=gc();
return x*f;
}
#define no return puts("Poor Coke!"), 0;
int n, m, r, L, a[N], b[N], l[N], p[N], F[N]; bool flag[N];
int f[N][N], g[N][M];
inline void upd(int &x, int y) {x=y>x?x:y;}
struct monoque
{
struct node {int l, f;} q[N];
int hh=1, tt;
inline int query(int x)
{
while(hh<=tt && q[hh].l<x) ++hh;
return hh<=tt?q[hh].f:inf;
}
inline void upd(int l, int f)
{
while(hh<=tt && q[tt].f>=f) --tt;
q[++tt]={l, f};
}
} q[M];
int main()
{
#ifdef Jerrywang
freopen("E:/OI/in.txt", "r", stdin);
#endif
n=read(), m=read(), r=read(), L=read(); r=min(r, n+n);
rep(i, 1, n) a[i]=read(), b[i]=read(), l[i]=read(), p[i]=read(), F[i]=read();
rep(i, 1, n) if(l[i]-l[i-1]>L) no
memset(f, -0x3f, sizeof f);
f[0][0]=0;
rep(i, 1, n)
{
rep(j, 0, m)
{
f[i][j]=f[i-1][j];
if(j>=a[i]) f[i][j]=max(f[i][j], f[i-1][j-a[i]]+b[i]);
}
}
int mxj=0;
rep(j, 1, m) if(f[n][j]>f[n][mxj]) mxj=j;
int j=mxj;
for(int i=n; i; i--)
{
if(j>=a[i] && f[i][j]==f[i-1][j-a[i]]+b[i])
j-=a[i], flag[i]=1;
}
memset(g, 0x3f, sizeof g);
g[0][r]=0; q[r].upd(0, 0);
int pre=0;
rep(i, 1, n)
{
rep(j, 0, r)
{
if(p[i] && j) upd(g[i][j], g[i][j-1]+p[i]);
int lo=max(pre, l[i]-L);
upd(g[i][j], q[j+2].query(lo)+F[i]);
q[j].upd(l[i], g[i][j]);
}
if(flag[i]) pre=l[i];
}
int res2=inf;
rep(j, 0, r) upd(res2, g[n][j]);
if(res2==inf) no
printf("%d %d", f[n][mxj], f[n][mxj]-res2);
return 0;
}