Doing Homework题解
Doing Homework题解
我们最好预先处理好每个时间节点满足条件的最小费用,
然后贪心的处理就行。
预处理呢,
可以用背包:\(f[i][j]:\)表示第i个时间点做了j吨作业的最小精力
但是我们并不好进行截止日期的删除操作,
所以我们倒过来搞就行了。
#include<bits/stdc++.h>
using namespace std;
const int N=5006,M=5000;
int n,W,X,t,ans=0,val,o=0,f[2][N],dp[N];
struct hw{int x,w,t;}q[N];
inline int read(){
int T=0,F=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
return F*T;
}
bool cmp(hw u,hw v){return u.t<v.t;}
int main(){
X=read(),W=read(),n=read();
for(int i=1;i<=n;++i) q[i].x=read(),q[i].w=read(),q[i].t=read();
sort(q+1,q+n+1,cmp),memset(dp,0x3f,sizeof(dp)),memset(f,0x3f,sizeof(f));
f[0][0]=f[1][0]=0;
for(int i=n;i>=1;--i){
o^=1;
for(int j=0;j<=M;++j){
f[o][j]=f[o^1][j];
if(j>=q[i].w) f[o][j]=min(f[o][j],f[o][j-q[i].w]+q[i].x);
if(j>=W) dp[i]=min(dp[i],f[o][j]);
}
}
for(int i=1;i<=n;++i){
if(q[i].t==q[i-1].t) continue;
t=dp[i],val=X/t;
if(val<q[i].t-q[i-1].t){ans+=val,X-=val*t; break;}
else ans+=q[i].t-q[i-1].t,X-=(q[i].t-q[i-1].t)*t;
}
printf("%d %d\n",ans,X);
return 0;
}