传送门:https://www.luogu.org/problem/U91353
这道题,我太弱了QWQ,爆搜过两个点走人......
先想想,这道题一眼DP,但是状态想出来了,决策就不会了,这道题的决策依赖于贪心
把每个点的按T[i]/L[i] 从小到大排序,然后当一个背包做。(!!!判断合法状态!!!)
贪心证明可以考虑临项交换。(不在证明(
还有一点就是背包的体积要开多少?
如果超过最大的E[i]就没用了。想想为什么?
最小的L[i]也有1 (为0的可以直接统计到答案,那是白给的) 所以不会超过max{E[i]}
#include<cstdio> #include<algorithm> #include<cstring> #define R register using namespace std; int T,n,cnt,ans,sum,dp[21000]; struct ddd{ int e,l,t; }p[120]; inline bool com(ddd a,ddd b){ return a.t*b.l<=b.t*a.l; } int main (){ scanf("%d",&T); while(T--){ ans=0,sum=0,cnt=0; memset(dp,0,sizeof(dp)); scanf("%d",&n); for(R int i=1;i<=n;i++){ cnt++; scanf("%d%d%d",&p[cnt].e,&p[cnt].l,&p[cnt].t); if(p[cnt].l==0) sum+=p[cnt].e,cnt--; } sort(p+1,p+1+cnt,com); for(R int i=1;i<=cnt;i++){ for(R int j=20000;j>=p[i].t;j--){ dp[j]=max(dp[j],(p[i].e-p[i].l*(j-p[i].t))>=0? dp[j-p[i].t]+(p[i].e-p[i].l*(j-p[i].t)):0 ); } } for(R int i=1;i<=20000;i++) ans=max(ans,dp[i]); printf("%d ",ans+sum); } return 0; }