bzoj1855: [Scoi2010]股票交易
背包
感觉省选怎么会考这么简单的东西呢 无聊去网上搜了一下 发现原来正解是单调队列来优化呀
不过带个log问题也不大
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<string> 7 8 using namespace std; 9 10 void setIO(const string& a) { 11 freopen((a+".in").c_str(), "r", stdin); 12 freopen((a+".out").c_str(), "w", stdout); 13 } 14 15 const int N = 2010, INF = 0x3f3f3f3f; 16 17 int f[N][N], g[N]; 18 19 template<typename Q> void maxit(Q& x, const Q& y) { 20 if(x < y) x = y; 21 } 22 23 int main() { 24 25 int n, maxp, w, ap, bp, as, bs; 26 scanf("%d%d%d", &n, &maxp, &w); 27 28 memset(f, -0x3f, sizeof f); 29 30 f[1][0] = 0; 31 32 for(int sum, ok, k, i = 1; i <= n; i++) { 33 scanf("%d%d%d%d", &ap, &bp, &as, &bs); 34 memcpy(g, f[i], sizeof g); 35 int tmr = min(i + 1 + w, n + 1); 36 for(ok = 1, sum = 0, k = 1; ok; k <<= 1) { 37 if(sum + k <= as) sum += k; 38 else k = as - sum, ok = 0; 39 for(int j = maxp; j >= 0; j--) if(g[j] > -INF) {// buy 40 if(j + k <= maxp) maxit(g[j + k], g[j] - ap * k); 41 } 42 } 43 // memcpy(g, f[i], sizeof g); 44 for(ok = 1, sum = 0, k = 1; ok; k <<= 1) { 45 if(sum + k <= bs) sum += k; 46 else k = bs - sum, ok = 0; 47 for(int j = 0; j <= maxp; j++) if(g[j] > -INF) {// sell 48 if(j - k >= 0) maxit(g[j - k], g[j] + bp * k); 49 } 50 } 51 for(int j = 0; j <= maxp; j++) { 52 maxit(f[i + 1][j], f[i][j]); 53 maxit(f[tmr][j], g[j]); 54 } 55 } 56 int ans = 0; 57 for(int i = 0; i <= maxp; i++) ans = max(ans, f[n + 1][i]); 58 printf("%d\n", ans); 59 60 return 0; 61 }
原文出处http://www.cnblogs.com/showson/