zoukankan      html  css  js  c++  java
  • [SCOI2010]股票交易

    题面传送


    这题好想,dp嘛。但是转移容易漏。
    (dp[i][j])表示第(i)天,手里有(j)股时的最大利润,那么
    1.啥也不干:(dp[i][j] = dp[i - 1][j]).
    2.凭空买(前几天啥也不干):(dp[i][j] = max {dp[i][j], -j * ap[i]}).(我就漏了这个)
    3.在第(i)天买(j-k)股:(dp[i][j] = max {dp[i - w - 1][k] - (j - k) * ap[i] }(0 leqslant j-k leqslant as[i])).
    4.同理,在第(i)天卖(j - k)股:(dp[i][j] = max {dp[i - w - 1][k] + (j - k) * bp[i]}(0 leqslant j - k leqslant bs[i])).


    对于“买”这个式子(卖同理),稍微变形一下:(dp[i][j] = max {dp[i - w - 1][k] + k * ap[i] } - j * ap[i]),就变成了滑动窗口问题了,单调队列可以解决。


    做法就是对于每一层,正着和倒着跑一遍单调队列,分别处理买和卖两个转移。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<queue>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef double db;
    const ll INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 2e3 + 5;
    In ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), las = ' ';
    	while(!isdigit(ch)) las = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(las == '-') ans = -ans;
    	return ans;
    }
    In void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    int n, m, w;
    int ap[maxn], bp[maxn], as[maxn], bs[maxn];
    
    int dp[maxn][maxn];
    deque<int> q;
    In void work1()
    {
    	for(int i = 1; i <= n; ++i)
    	{
    		for(int j = 0; j <= m; ++j) 
    		{
    			dp[i][j] = dp[i - 1][j];
    			if(j <= as[i]) dp[i][j] = max(dp[i][j], -j * ap[i]); 
    		}
    		if(i <= w) continue;
    		q.clear();
    		for(int j = 0; j <= m; ++j)
    		{
    			int* D = dp[i - w - 1];			
    			while(!q.empty() && D[q.back()] + q.back() * ap[i] <= D[j] + j * ap[i]) q.pop_back();
    			while(!q.empty() && q.front() < j - as[i]) q.pop_front();
    			q.push_back(j);
    			dp[i][j] = max(dp[i][j], D[q.front()] - (j - q.front()) * ap[i]);
    		}
    		q.clear();
    		for(int j = m; j >= 0; --j)
    		{
    			int* D = dp[i - w - 1]; 
    			while(!q.empty() && D[q.back()] + q.back() * bp[i] <= D[j] + j * bp[i]) q.pop_back();
    			while(!q.empty() && q.front() - j > bs[i]) q.pop_front();	
    			q.push_back(j);
    			dp[i][j] = max(dp[i][j], D[q.front()] + (q.front() - j) * bp[i]);
    		}
    	}
    	int ans = -INF;
    	for(int i = 0; i <= m; ++i) ans = max(ans, dp[n][i]);
    	write(ans), enter;
    }
    
    int main()
    {
    	n = read(), m = read(), w = read();
    	for(int i = 1; i <= n; ++i)
    		ap[i] = read(), bp[i] = read(), as[i] = read(), bs[i] = read();
    	Mem(dp, 128), dp[0][0] = 0;
    	work1();
    	return 0;
    }
    
  • 相关阅读:
    struts2(2.0.x到2.1.2版本)的核心和工作原理(转)
    关于Struts2通配符无效的说明
    contOS 网络配置
    INFORMATICA 开发规范
    Python tricks(1) -- 动态定义一个新变量
    MySQL connector c++使用笔记
    python使用set来去重碰到TypeError: unhashable type
    Redis 资料整理
    Ruby 安装和gem配置
    爱读书的犹太人
  • 原文地址:https://www.cnblogs.com/mrclr/p/14511211.html
Copyright © 2011-2022 走看看