DP专练4:[SCOI 2010]股票交易(单调队列优化dp)
昨天晚上,初見它時(shí),月黑風(fēng)高,一個(gè)電腦,一支筆,一個(gè)人
今天秋高氣爽,再一瞥,回眸間
我又來了,honey
- 題目
- 題解
- 代碼實(shí)現(xiàn)
題目
題解
首先這種 iii 天與前面 jjj 天有關(guān)聯(lián),而且讓你求最后一天的極值
我們一定會(huì)聯(lián)想到 DPDPDP
先搞定 dpdpdp 定義?
第一維毋庸置疑就是表示 iii 天,接著思考一下第二維 jjj
1)如果表示 iii 天買了或者賣了 jjj 股票,就遇到了一個(gè)問題,i?W?1i-W-1i?W?1 天的時(shí)候股票數(shù)又是多少呢?
難道我要再去用一重循環(huán)枚舉嗎?顯然不現(xiàn)實(shí)。
2)如果表示 iii 天手上還擁有著 jjj 股票( iii 天已經(jīng)操作完成了)
那么 ±k±k±k 就是 i?W?1i-W-1i?W?1 的股票數(shù)了
綜上 dp[i][j]:idp[i][j]:idp[i][j]:i 天手上的股票數(shù)為 jjj 時(shí)的最大收益。
最后輸出 dp[n][0]dp[n][0]dp[n][0] 就可以了,nnn 天的時(shí)候手上沒有股票數(shù)肯定是最優(yōu)解了,不然你手上捏著股票又買賣不了,拿來擦屁股嗎??
找到轉(zhuǎn)移方程式?
-
這一天閑得慌,不買也不賣
dp[i][j]=dp[i?1][j](0≤j≤MaxP)dp[i][j]=dp[i-1][j] (0≤j≤MaxP)dp[i][j]=dp[i?1][j](0≤j≤MaxP)
-
這一天才開始玩股票,只能去購(gòu)進(jìn)股票
dp[i][j]=?j?api(j?asi≤k<j)dp[i][j]=-j*ap_i(j-as_i≤k<j)dp[i][j]=?j?api?(j?asi?≤k<j)
-
自由權(quán)比較大,手上有點(diǎn)資本,也要購(gòu)進(jìn)
dp[i][j]=dp[i?W?1][k]?(j?k)?api(j?asi≤k<j)dp[i][j]=dp[i-W-1][k]-(j-k)*ap_i(j-as_i≤k<j)dp[i][j]=dp[i?W?1][k]?(j?k)?api?(j?asi?≤k<j)
-
該開始賺錢錢了,賣一點(diǎn)股票出去
dp[i][j]=dp[i?W?1][k]+(k?j)?bpi(j<k≤j+bsi)dp[i][j]=dp[i-W-1][k]+(k-j)*bp_i(j<k≤j+bs_i)dp[i][j]=dp[i?W?1][k]+(k?j)?bpi?(j<k≤j+bsi?)
在這四種情況下,取一個(gè) maxmaxmax 即可。
那么為什么i-W-1就是當(dāng)前最優(yōu)解呢?
因?yàn)槲覀兪且惶煲惶爝f推過去的,當(dāng)前最優(yōu)解會(huì)被傳遞過去,
這也是我們DP需要完成的
分析這個(gè) DPDPDP 的時(shí)間復(fù)雜度,O(n3)O(n^3)O(n3)。
所以必須對(duì) kkk 優(yōu)化
我們就去拆一拆 case3 case4 的 DPDPDP 式
dp[i][j]=dp[i?W?1][k]?(j?k)?api(j?asi≤k<j)dp[i][j]=dp[i-W-1][k]-(j-k)*ap_i(j-as_i≤k<j)dp[i][j]=dp[i?W?1][k]?(j?k)?api?(j?asi?≤k<j)?\Downarrow ?dp[i][j]=dp[i?W?1][k]+k?api?j?api(j?asi≤k<j)dp[i][j]=dp[i-W-1][k]+k*ap_i-j*ap_i(j-as_i≤k<j)dp[i][j]=dp[i?W?1][k]+k?api??j?api?(j?asi?≤k<j)
我們會(huì)發(fā)現(xiàn) j?apij*ap_ij?api? 是固定不變的。
也就是說真正影響 dp[i][j]dp[i][j]dp[i][j] 的是 dp[i?W?1][k]+k?apidp[i-W-1][k]+k*ap_idp[i?W?1][k]+k?api?
而且 dp[i?W?1][k]+k?apidp[i-W-1][k]+k*ap_idp[i?W?1][k]+k?api? 越大越好。
發(fā)現(xiàn)這個(gè)方程的實(shí)質(zhì)是 k∈[j?asi,j)k∈[j-as_i,j)k∈[j?asi?,j) 這個(gè)范圍內(nèi)取得的且只和 kkk 有關(guān)。
dp[i][j]=dp[i?W?1][k]+(k?j)?bpi(j<k≤j+bsi)dp[i][j]=dp[i-W-1][k]+(k-j)*bp_i(j<k≤j+bs_i)dp[i][j]=dp[i?W?1][k]+(k?j)?bpi?(j<k≤j+bsi?)?\Downarrow?dp[i][j]=dp[i?W?1][k]+k?bpi?j?bpi(j<k≤j+bsi)dp[i][j]=dp[i-W-1][k]+k*bp_i-j*bp_i(j<k≤j+bs_i)dp[i][j]=dp[i?W?1][k]+k?bpi??j?bpi?(j<k≤j+bsi?)
我們會(huì)發(fā)現(xiàn) j?bpij*bp_ij?bpi? 是固定不變的。
也就是說真正影響 dp[i][j]dp[i][j]dp[i][j] 的是 dp[i?W?1][k]+k?bpidp[i-W-1][k]+k*bp_idp[i?W?1][k]+k?bpi?
而且 dp[i?W?1][k]+k?bpidp[i-W-1][k]+k*bp_idp[i?W?1][k]+k?bpi? 越大越好。
發(fā)現(xiàn)這個(gè)方程的實(shí)質(zhì)是 k∈(j,j+bsi]k∈(j,j+bs_i]k∈(j,j+bsi?] 這個(gè)范圍內(nèi)取得的且只和k有關(guān)
結(jié)合以上兩種情況:就會(huì)聯(lián)想到我們的單調(diào)隊(duì)列了。
維護(hù) kkk 的范圍而且從大到小,每次取隊(duì)頭 headheadhead 進(jìn)行更值
這樣就轉(zhuǎn)化成了O(n2)O(n^2)O(n2)。
最后注意一下循環(huán)順序
買股票就從小到大 0~MaxP0\sim MaxP0~MaxP
賣股票就從大到小 MaxP~0MaxP\sim 0MaxP~0
代碼實(shí)現(xiàn)
#include <cstdio> #include <iostream> using namespace std; #define MAXN 2005 int T, MaxP, W; int ap, bp, as, bs; int head, tail; int deq[MAXN]; int dp[MAXN][MAXN]; int main() {scanf ( "%d %d %d", &T, &MaxP, &W );++ W;dp[0][0] = -MAXN * MAXN;for ( int i = 1;i <= MaxP;i ++ )dp[0][i] = dp[0][i - 1];for ( int i = 1;i <= T;i ++ ) {scanf ( "%d %d %d %d", &ap, &bp, &as, &bs );for ( int j = 0;j <= MaxP;j ++ )dp[i][j] = dp[i - 1][j];for ( int j = 0;j <= as;j ++ )dp[i][j] = max ( dp[i][j], -j * ap );if ( i > W ) {head = 1, tail = 0;for ( int j = 0;j <= MaxP;j ++ ) {while ( head <= tail && deq[head] < j - as )head ++;while ( head <= tail && deq[tail] * ap + dp[i - W][deq[tail]] <= j * ap + dp[i - W][j] )-- tail;deq[++ tail] = j;dp[i][j] = max ( dp[i][j], dp[i - W][deq[head]] + deq[head] * ap - j * ap );}head = 1, tail = 0;for ( int j = MaxP;j >= 0;j -- ) {while ( head <= tail && deq[head] > j + bs )head ++;while ( head <= tail && deq[tail] * bp + dp[i - W][deq[tail]] <= j * bp + dp[i - W][j] )tail --;deq[++ tail] = j;dp[i][j] = max ( dp[i][j], dp[i - W][deq[head]] + deq[head] * bp - j * bp );}}}printf ( "%d", dp[T][0] );return 0; }總結(jié)
以上是生活随笔為你收集整理的DP专练4:[SCOI 2010]股票交易(单调队列优化dp)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 常见的传统毒品有哪些 毒品的分类
- 下一篇: 伤心的个性签名