HDU

来源:互联网 发布:我的世界地狱门算法 编辑:程序博客网 时间:2024/06/06 19:17

大家都很强, 可与之共勉。

Problem Description

Recently, lxhgww is addicted to stock, he finds some regular patterns after a few days’ study.
He forecasts the next T days’ stock market. On the i’th day, you can buy one stock with the price APi or sell one stock to get BPi.
There are some other limits, one can buy at most ASi stocks on the i’th day and at most sell BSi stocks.
Two trading days should have a interval of more than W days. That is to say, suppose you traded (any buy or sell stocks is regarded as a trade)on the i’th day, the next trading day must be on the (i+W+1)th day or later.
What’s more, one can own no more than MaxP stocks at any time.

Before the first day, lxhgww already has infinitely money but no stocks, of course he wants to earn as much money as possible from the stock market. So the question comes, how much at most can he earn?

Input

The first line is an integer t, the case number.
The first line of each case are three integers T , MaxP , W .
(0 <= W < T <= 2000, 1 <= MaxP <= 2000) .
The next T lines each has four integers APi,BPi,ASi,BSi( 1<=BPi<=APi<=1000,1<=ASi,BSi<=MaxP), which are mentioned above.

Output
The most money lxhgww can earn.

Sample Input
1
5 2 0
2 1 1 1
2 1 1 1
3 2 1 1
4 3 1 1
5 4 1 1

Sample Output
3

很容易想到转移方程式:对比前一次买进股票dp[i][j]=dp[i-w-1][k]-(j-k)*ap 抛出股票dp[i][j]=dp[i-w-1][k]+(j-k)*bp dp数组表示i天,手头有j支股票时赚的钱,单看这个方程时间复杂度达到三次方,用单调队列优化能降一维,具体操作呢?其实我没懂为啥要这么替换,应该是套路吧。对于抛出股票的行为,tmp=dp[k][j]+bp*j,维护单调队列,。j从m遍历到0,每次计算tmp插入单调队列中,这个操作说起来很纠结,也可能是我想错了,欢迎指正,插入队列时j的意义在于将上一次的值插入,然后取队首元素作为最大值,等到dp的递推就是求得当前的最大值,然后因为是卖出去,所以遍历是从大到小,我们设的v[]与实际的dp[]数组相差-bp*j,我们维护单调队列的意义在于每次及时找到当前的最大值嘛,递推dp的时候把差的加上就好。还有就是控制一次性抛出的最大值:这个时候j的意义就变成是当前值了,当前的股票数量-队首元素的股票数量若大于bs,一直出队列。

#include "cctype"#include "cstdio"inline short readIn(int& x)  {    static char ch;    while( !isdigit(ch = getchar()) && (ch ^ -1));    if(ch == -1)    return 0;    for(x = -48 + ch; isdigit(ch = getchar()); x = x * 10 + ch - 48);    return 1;}#define max(a, b)  ((a) > (b) ? (a) : (b))struct Data  {    int v, id;    Data() {    }    Data(int v, int id) : v(v), id(id)  {   }};template<class T>class deque  {private:    T v[4005];    int fr, tl;public:    deque() : fr(2001), tl(2000) {  }    inline void clear()  {        this -> fr = 2001, this -> tl = 2000;    }    inline void push_front(T S)  {        v[--fr] = S;        }    inline void push_back(T S)  {        v[++tl] = S;        }    inline void pop_front()  {        ++fr;    }    inline void pop_back()  {        --tl;    }    inline Data front()  {        return v[fr];    }    inline Data back()  {        return v[tl];    }    inline short empty()  {        return fr > tl;    }};deque <Data> q;int dp[2005][2005], TT, T, maxp, w, ap, bp, as, bs, k, tmp, t;int main ()  {    register int i, j;    for(readIn(TT); TT; --TT)  {        readIn(T); readIn(maxp); readIn(w);        for(i = 1, t = w + 1; i <= t; ++i)  {            readIn(ap); readIn(bp); readIn(as); readIn(bs);            for(j = 0; j <= maxp; ++j)            dp[i][j] = (j <= as) ? -ap * j : -0x3f3f3f3f,            i ^ 1 ? dp[i][j] = max(dp[i - 1][j], dp[i][j]) : 1;        }        for(i = w + 2; i <= T; ++i)  {            q.clear();            readIn(ap); readIn(bp); readIn(as); readIn(bs);            k = i - w - 1;            for(j = 0; j <= maxp; ++j)  {                tmp = dp[k][j] - ap * (maxp - j);                while( !q.empty() && q.back().v < tmp )  q.pop_back();                q.push_back(Data(tmp, j));                while(j - q.front().id > as)  q.pop_front();                dp[i][j] = max(dp[i - 1][j], q.front().v + ap * (maxp - j));            }            q.clear();            for(j = maxp; ~j; --j)  {                  tmp = dp[k][j] + bp * j;                  while( !q.empty() && q.back().v < tmp )  q.pop_back();                q.push_back(Data(tmp, j));                while(q.front().id - j > bs)  q.pop_front();                dp[i][j] = max(dp[i][j], q.front().v - bp * j);              }          }        printf("%d\n", dp[T][0]);    }}
0 0
原创粉丝点击