一般來說,有動態規劃思想的都是動態規劃水題。
當然,前提是你完全理解了動態規劃思想
給定你一些數,要求你找乙個區間,要求這個區間內的數的和乘以這個區間內最小的數,要求這個積最大。
簡直蒙蔽,
後來發現說單調棧也能寫,但是不會單調棧。。
看懂題解了,
就是先沒個數左邊的數(這是確定的,並且要從左往右求,這樣可以利用前面的結果。)
往右也是這樣。
還有一點畫龍點睛的就是
看資料範圍,改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,子狀態之間的轉換 即遞迴求解,子狀態到上一級子狀態之間的變換關係 即如何從乙個或多個值已知的狀態,求...