Loj #2256. 「SNOI2017」英雄聯盟
阿新 • • 發佈:2019-03-27
can 最小花費 tps 很多 最小 string loj getchar() ble
題目
我就是個絲薄
如果要用\(dp_i\)表示湊出\(i\)的最小花費顯然不可能的
之後大力猜想能湊出來的狀態不會很多,我的暴力也告訴我不是很多,好像也確實不多的樣子,大概\(4e4\)左右
但是我就這樣思維僵化了,背包套路難道不是看到某一維特別大就把交換一下這一維和\(dp\)值嗎
於是\(dp_i\)表示使用\(i\)的費用湊出的最大的數
分組背包大力轉移即可
代碼
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define re register #define LL long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) const int maxn=150; inline int read() { char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x; } int n,a[maxn],b[maxn],now[maxn]; LL m; LL dp[2000*150]; int main() { n=read();scanf("%lld",&m); for(re int i=1;i<=n;i++) a[i]=read(); for(re int i=1;i<=n;i++) b[i]=read(); for(re int i=1;i<=n;i++) now[i]=now[i-1]+a[i]*b[i]; memset(dp,-1,sizeof(dp)); dp[0]=1; for(re int i=1;i<=n;i++) { for(re int j=now[i];j;--j) for(re int k=2;j-k*b[i]>=0&&k<=a[i];++k) dp[j]=max(dp[j],dp[j-k*b[i]]*k); } for(re int i=0;i<=now[n];i++) if(dp[i]>=m) return printf("%d\n",i),0; return 0; }
Loj #2256. 「SNOI2017」英雄聯盟