區間dp狀態設計的通常形式c++
區間dp通常就是設dp[i][j]表示區間[i,j]所能造成的最優答案或者方案數。spa
或者像序列同樣,多加幾維表示附加的信息。設計
poj3280code
給你長度爲m的字符串,其中有n種字符,每種字符都有兩個值,分別是插入這個字符的代價,刪除這個字符的代價,讓你求將原先給出的那串字符變成一個迴文串的最小代價。blog
M<=2000字符串
dp[i][j]表明區間i到區間j成爲迴文串的最小代價,那麼對於dp[i][j]有三種狀況:it
一、dp[i+1][j]表示區間i+1到區間j已是迴文串了的最小代價,那麼對於s[i] 這個字母,咱們有兩種操做,刪除與添加,對應有兩種代價, dp[i+1][j]+add[s[i]]或dp[i+1][j]+del[s[i]],取這兩種代價的最小值。class
二、dp[i][j-1]表示區間i到區間j-1已是迴文串了的最小代價,那麼對於s[j] 這個字母,一樣有兩種操做,dp[i][j-1]+add[s[j]]或dp[i][j-1]+del[s[j]],取最小值。im
三、如果s[i]==s[j],dp[i+1][j-1]表示區間i+1到區間j-1已是迴文串的最小代價,那麼對於這種狀況,咱們考慮dp[i][j]與dp[i+1][j-1]的大小img
而後dp[i][j]取上面這些狀況的最小值便可。
括號最大匹配
給你一串()[]括號,要你求出這串括號的最大匹配個數,如'('與')'匹配,爲 2個,'['與']'匹配,爲2個,其餘不能匹配.......
容許有雜質即( [ ( [ ] ] ) ] 應該是 [ ( [ ] ) ]//去掉雜質
就是選出一個最長合法子括號序列。
序列的長度小於等於100。
dp[i][j]表明從區間i到區間j所匹配的括號的最大個數,首先,假設不匹配, 那麼dp[i][j]=dp[i+1][j];
而後查找i+1~~j有木有與第i個括號匹配的,
有的話,dp[i][j]=max(dp[i][j],dp[i+1][k-1]+dp[k+1][j]+2)//其中c[i]與c[k]匹配。
爲何和上一題不同?
由於()()()()….而非僅僅是(((())))
bzoj1900
摺疊的定義以下:
1. 一個字符串能夠當作它自身的摺疊。
2. X(S)是X(X>1)個S鏈接在一塊兒的串的摺疊。記做X(S) = SSSS…S(X個S)。
3. 若是A = A’, B=B’,則AB =A’B’ 例如,由於3(A) = AAA, 2(B) = BB,因此
3(A)C2(B) = AAACBB,而2(3(A)C)2(B)=AAACAAACBB
給一個字符串,求它的最短折疊。例如AAAAAAAAAABABABCCD的最短折疊爲:9(A)3(AB)CCD。
輸入字符串長度小於等於100。
f[l][r]表示,把l~r這個區間摺疊的最短長度,而後咱們想,對於一個區間來講,咱們有兩種選擇,一種是把這個區間它本身來摺疊,另外一種是兩塊已經摺疊的區間接起來。
對於第二種狀況,直接枚舉斷點(區間dp中很常見),找最小的一種方案,第一種則是,找出它全部的摺疊方案,在摺疊方案中取一個最優的。
思路的整理類比和分析:總體的思路都是對於一段區間,兩類決策
1:枚舉斷點,由子問題更新的最優決策。
2:該區間自己進行壓縮(進行處理)的最優決策。
通常1000考慮邊界,100枚舉斷點
環形問題
環形問題有一個很常見的處理辦法是,斷環爲鏈,而後把這個鏈複製一遍接在原鏈的後面。
而後作區間dp,最後取答案就是找dp[i][i+n-1]裏面取最優的便可。
在讀入的時候現將珠子們複製一遍放到後面,斷環成鏈
設f[j][i]表示左端點爲j號珠子,右端點爲i號珠子的區間所能獲得的最大能量,轉移就枚舉最後一步聚合的位置便可。
代碼:
#include<bits/stdc++.h> using namespace std; int head[205],tail[205],f[205][205]; int n,ans; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&head[i]); head[i+n]=head[i]; } for(int i=1;i<=n*2-1;i++) tail[i]=head[i+1]; tail[n+n]=head[1]; for(int i=1;i<=n-1;i++) { for(int j=1;j<=2*n-i;j++) { int t=i+j; for(int k=j;k<=t-1;k++) f[j][t]=max(f[j][t],f[j][k]+f[k+1][t]+head[j]*tail[k]*tail[t]); } } for(int i=1;i<=n;i++) { ans=max(ans,f[i][i+n-1]); } cout<<ans; }