第乙個單調佇列優化dp
寫了半天,最後初始化搞錯了還一直wa。。
題目大意:
**,總共 t 天,每天可以**na[i]股,賣出nb[i]股,價錢分別為pa[i]和pb[i],最大同時擁有p股
且一次交易後至少要間隔w天才能再次交易,初始有0股,本金無限,求最大收益
題解:dp[i][j]表示第 i 天,有 j 股的最大收益
狀態轉移 dp[i][j]=max
複雜度 為 t*t*p*p
首先我們可以看出 dp[i][j]>=dp[i-1][j](不買不賣轉移)
所以可以將 r 確定為 i-w-1,複雜度變為t*p*p 還是很大
然後對於買,移項有
dp[i][j]+j*pa[i]=dp[r][k]+k*pa[i]。右邊與 j無關, 可見我們只需要對每乙個 i 維護乙個關於k的單調佇列,就可以在 p時間內求出所有的dp[i][j]
複雜度降為 t*p 可以接受了
最後注意下邊界條件:
1到w+1的都是從初始條件下轉移的
**:
#include #include#include
#include
#include
#include
using
namespace
std;
#define maxn 2000
#define inf 200000000
int na[maxn+10],nb[maxn+10],pa[maxn+10],pb[maxn+10
];int dp[maxn+10][maxn+10
];int
t,p,w;
typedef
struct
node
node;
typedef
struct
dqueue
void
clear()
node front()
void
pop()
void
push(node x)
if(x.val>q[l].val)
for(int i=r;i>l;i--)
}q[r++]=x;
}}dqueue;
dqueue qa,qb;
int buy(int now,int
n)
else
break
; }
return
tmp.val;
}int sale(int now,int
n)
else
break
; }
return
tmp.val;
}void
dp()
}node no;
for(int i=1;i<=w+1;i++)
for(int j=0;j<=p;j++)
}for(int i=w+2;i<=t;i++)
for(int j=0;j<=p;j++)
dp[i][j]=max(dp[i][j],dp[i-1][j]); //
不買int tmp=buy(i,j);
dp[i][j]=max(dp[i][j],tmp-j*pa[i]); //
買 tmp=sale(i,j);
dp[i][j]=max(dp[i][j],tmp-j*pb[i]); //賣}
}}int
main()
dp();
int ans=0
;
for(int i=0;i<=p;i++)
printf(
"%d\n
",ans);
}return0;
}
hdu 3401 單調佇列優化動態規劃
思路 動態方程很容易想到dp i j max dp i j dp i w 1 j k k ap i dp i w 1 j k k bp i dp i j 表示第i天擁有j個石頭的最大價值。其實每次求得都是最有策略,所有dp i w 1 表示的就是i w 1以前的最優,故不同往前遍歷。那麼主要需要優化...
HDU 3401 Trade 單調佇列優化dp
題目大意 現在要你去 給你每天的開盤價值,每股 價值為ap,賣出價值為bp,每天最多買as股,最多賣出bs股,並且要求兩次買賣必須間隔w天,問你在t天內如何進行 操作從而獲得最大收益。解題思路 先吐槽一下,會單調佇列但不會dp不行,會dp但不會單調佇列也不行!開始dp動態轉移方程倒是寫對了,然後算算...
HDU3401 Trade 單調佇列優化dp
分析可以設定二維的dp狀態i天有j塊錢的最大收益 對w 1天之前的每天進行初始化,因為在這個時候只能買,也可以不買,但是這個不買在後面進行集體操作 之後就有3種情況,一種是買,一種是不操作,一種賣出 並且只有當滿足條件的時候才能進行買賣,那麼這個優化方法就明顯了,不買的情況就是等於前一天這個錢的大小...