上周的忘写了……题目没有作者……
T1.backpack
期望得分100,实际得分100.
感觉我自己真是不如以前了……以前做这种题都是秒掉的,现在怎么想了10分钟啊……
因为物品的体积和价值都非常小,我们有一句套话,“远距离贪心,近距离暴力”,所以虽然背包的体积特别大,我们可以把他压缩成1000000左右,剩下的直接暴力取性价比最高的即可。
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 10000005; const int INF = 1000000009; const ll mod = 1e9+7; ll read() { ll ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } ll dp[M],m,n,a[M],b[M],v[105],mpos,ans; double maxn; void solve1() { rep(i,1,n) rep(j,a[i],m) dp[j] = max(dp[j],dp[j-a[i]] + b[i]); printf("%lld\n",dp[m]); } int main() { freopen("backpack.in","r",stdin); freopen("backpack.out","w",stdout); n = read(),m = read(); rep(i,1,n) { a[i] = read(),b[i] = read(); v[a[i]] = max(b[i],v[a[i]]); } if(n <= 10000 && m <= 10000) solve1(); else { rep(i,1,100) { double p = (double)(i),q = (double)(v[i]); if(q / p > maxn) maxn = q / p,mpos = i; } if(m > 100000) { ll k = (m - 100000) / mpos; m -= k * mpos,ans += k * v[mpos]; } rep(i,1,100) rep(j,i,m) dp[j] = max(dp[j],dp[j-i] + v[i]); ans += dp[m]; printf("%lld\n",ans); } return 0; }