bzoj5018: [Snoi2017]英雄联盟
10.5重回bzoj。刷了这道背包DP交了10次。
不过这个真的是一道好题。(也许是我DP太烂)
由于钱数较小,容易想到,f[i]表示花了i元所有的展示策略个数。然而在DP的时候却有一个问题,我们枚举买的皮肤个数维护背包时,有可能同一个英雄不同皮肤数叠乘,这样就不对了,所以DP时先从后将更新的位置枚举出来,再枚举买皮肤个数,这样就不会重复。
#include<cstdio> #include<iostream> #include<cstring> using namespace std; typedef long long LL; LL f[1100000],a[1100],c[1100]; int main() { LL n,m; scanf("%lld%lld",&n,&m); if(m<=1){printf("0\n");return 0;} for(int i=1;i<=n;i++)scanf("%lld",&a[i]); for(int i=1;i<=n;i++)scanf("%lld",&c[i]); memset(f,0,sizeof(f));f[0]=1; LL sum=0,ans=2147483647; for(int i=1;i<=n;i++) { if(a[i]<=1)continue; sum+=a[i]*c[i]; for(int j=min(ans,sum);j>=2*c[i];j--) { for(int k=2;k<=a[i];k++) { if(k*c[i]>j)break; f[j]=max(f[j],f[j-k*c[i]]*k); } if(f[j]>=m)ans=j; } } printf("%lld",ans); return 0; }
pain and happy in the cruel world.