poj2796 動態規劃思想 回溯 單調棧第一題

2021-07-30 20:02:16 字數 2029 閱讀 3745

一般來說,有動態規劃思想的都是動態規劃水題。

當然,前提是你完全理解了動態規劃思想

給定你一些數,要求你找乙個區間,要求這個區間內的數的和乘以這個區間內最小的數,要求這個積最大。

簡直蒙蔽,

後來發現說單調棧也能寫,但是不會單調棧。。

看懂題解了,

就是先沒個數左邊的數(這是確定的,並且要從左往右求,這樣可以利用前面的結果。)

往右也是這樣。

還有一點畫龍點睛的就是

看資料範圍,改long long;

2 首尾的初始化要搞明白,不然會出事的

#include 

using namespace std;

/*poj 2796 feel food

給定乙個區間,求這個區間的和,再乘以這個區間內最小的,要求結果最大。

dp思想進行的操作

我不知道他叫什麼,不過應該和單調棧不一樣。

單調棧也可以寫哦

是用dp的思想,而那個 lr的陣列好想kmp的next陣列。

*/long

long a[100006];

int lef[100006];

int r[100006];

long

long

sum[100006];

int main()

a[0]=-9999;

a[n+1]=-99999;

//初始化過程,把這個結果的

for(int i=1;i<=n;i++)

else}}

//for(int i=0;i<=n;i++)

//printf("%d ",lef[i]);

//cout=1;i--)

else}}

long

long all=(sum[r[1]]-sum[lef[1]-1])*a[1];

//coutlong ans=0;

int ri=r[1];

int l=lef[1];//初始化應該是他的最左和最右。

for(int i=2;i<=n;i++)

方法2 利用單調棧

單調棧是一種資料結構,保證棧頂元素是最小的。

用來求乙個陣列中某個數占的區間。

別人說這是單調棧的經典題。。

維護乙個單調遞增的棧就行,

如果要加的元素比他就行。比他小。就更新他的左延伸。

(我已經比他小了,肯定比他範圍內的任何數最小啊。)

同時如果還有數,那麼就更新他的右延伸。cin竟然會tle。。

另外有一種特殊化的情況。所以ans的要設定為第乙個數。哈

#include 

#include

#include

#include

using

namespace

std;

const

int maxn=100006;

typedef

long

long ll;

struct node

;int main()

stack

s; node tmp;

tmp.k=1;

tmp.v=a[1];

tmp.l=1;

tmp.r=1;

s.push(tmp);

ll ans=a[1];

long

long ll=1;

long

long rr=1;

for(int i=2;i<=m;i++)

}s.push(tmp);

}//開始是維護乙個單調棧,把一些位置尷尬的數給去掉了

//但是裡面還保留著一些數,需要把他們清掉

while(!s.empty())

}if(m==0) ll=rr=ans=0;

printf("%lld\n%lld %lld\n",ans,ll,rr);

return

0;}

POJ 2796 字首陣列或者單調棧

poj 2796 題意 給出乙個陣列,求出某乙個數字和其所在的區間和的乘積最大值,輸出最大值和左右區間的邊界。其區間的定義是比這個數字大的區間。思路 正常的思路是列舉求出每乙個數字的區間,然後算出乘積。問題是如何減少複雜度。這裡可以用陣列的字首和。左右區間的話也可以加速比較。比如左區間 a i a ...

單調棧的進一步理解,poj2796

對於單調棧,則是乙個單調的棧,為什麼可以把複雜度減小為0 n 主要是在求以乙個數為最小的區間和的時候,可以在資料處理時構建乙個單調棧,已知乙個單調的棧,再往下面壓入乙個數時,如果不滿足單調性,則表明暫棧頂元素最小的區間已經結束了,那麼就pop出來,如果棧頂第二個元素也不滿足單調性,那麼也壓出,但是由...

動態規劃 思想

動態規劃 把問題劃分成子問題遞迴求解,並且保留中間結果以避免重複計算子問題的方法,叫動態規劃。eg 三角形路徑數字之和 關鍵思想 1,劃分成若干子問題 2,子問題的狀態,及若干狀態值 狀態的表述。3,子狀態之間的轉換 即遞迴求解,子狀態到上一級子狀態之間的變換關係 即如何從乙個或多個值已知的狀態,求...