1 条题解
-
0
首先我们设 表示前 项还剩 元和 个冰淇淋的最大受欢迎程度,简单分析,这样做时间复杂度为 级别的,无法通过本题。
我们可以感性理解一手,
其实是因为我也没理解透,不难发现冰淇淋并不是另外一个需要考虑的量,而是一个可以代替钱的优惠券。彬彬跟我聊天的时候给出了一个比喻:我们换钱的时候,总是考虑去汇率更大的银行换钱。
因此,这道题我们可以考虑以“贿赂”所需的冰淇淋的数量从小到大排序,前面的朋友等同于汇率更大的银行。
我们在前面用冰淇淋肯定比在后面用好。
简单证明一下,如果我们在后面用了冰淇淋,前面用了钱,可以将后面的冰淇淋换成钱,把前面的钱换成冰淇淋,这样钱数不变,花费的冰淇淋变少。
我们考虑枚举一个中间点,中间点以上全部使用冰淇淋,中间点以下全部使用钱,中间点两者皆可,求出最大受欢迎程度即可。
这就拆成了两个背包。
时间复杂度降为 。
#include<bits/stdc++.h> #define LL long long using namespace std; const LL N=2e3+5; struct node { LL p,c,x; }a[N]; LL n,m,k,f[N][N],g[N][N],ans; bool cmp(node x,node y) { return x.x<y.x; } int main() { scanf("%lld%lld%lld",&n,&m,&k); for(int i=1;i<=n;i++) { scanf("%lld%lld%lld",&a[i].p,&a[i].c,&a[i].x); } sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) { LL p=a[i].p,c=a[i].c*a[i].x; for(int j=0;j<=c-1&&j<=k;j++) { f[i][j]=f[i-1][j]; } for(int j=c;j<=k;j++) { f[i][j]=max(f[i-1][j],f[i-1][j-c]+p); } } for(int i=n;i>=1;i--) { LL p=a[i].p,c=a[i].c; for(int j=0;j<=c-1;j++) { g[i][j]=g[i+1][j]; } for(int j=c;j<=m;j++) { g[i][j]=max(g[i+1][j],g[i+1][j-c]+p); } } for(LL i=1;i<=n;i++) { for(LL j=0;j<=a[i].c&&j<=m;j++) { if((a[i].c-j)*a[i].x>k)continue; ans=max(ans,f[i-1][k-(a[i].c-j)*a[i].x]+a[i].p+g[i+1][m-j]); } } printf("%lld",ans); return 0; }
- 1
信息
- ID
- 7606
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 23
- 已通过
- 7
- 上传者