codeforces E - Selling Souvenirs
#记录一下自己一步一步跳进去的坑
1.比如说还在纠结为什么w明明不会太大为什么开longlong
因为不开的话这边会爆掉阿: return a.c*b.w>b.c*a.w;
2.比如说我的做法是把性价比排序,然后直接贪心选,剩下的再dp,同时卡一下边界
but一直卡不过去,开大了过不去T,开小了同样过不去wa
这是因为直接贪心选这个做法,不能保证正确性(属于我不能证伪,但数据测出来如此hh
看了一下其他人的写法,是贪心排序+dp,然后dp的优化在于:
for(int j=up;j>=max(f[i].w,1ll*up-1000);j--)
时间复杂度:O(1000*N),甚至1000还可以更小点,我觉得10左右就差不多,有人说6
这是因为在排序后,设想当前枚举到的容量上限为150,其实前100个最优解已经是固定的了
越枚举到后面,这个物件的价值越小,越不可能代替前面的更优的物件,去更新前面的答案
如果不会证明的话1000也够用啦>_<
#include<bits/stdc++.h> using namespace std; struct lys{long long w,c;}f[100007]; long long dp[300007]; int n,m; bool cmp(lys a,lys b){ return a.c*b.w>b.c*a.w; } void solve(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>f[i].w>>f[i].c; sort(f+1,f+n+1,cmp); long long up=0; for(int i=1;i<=n;i++) { up=min(up+f[i].w,1ll*m); for(int j=up;j>=max(f[i].w,1ll*up-1000);j--) dp[j]=max(dp[j],dp[j-f[i].w]+1ll*f[i].c); } long long ans=0; for(int i=1;i<=up;i++){ ans=max(ans,dp[i]); } cout<<ans; } int main(){ //freopen("lys.in","r",stdin); solve(); }