這裡我們都用到動態規劃的思想 dynamic programming,簡稱dp。
本質就是組合子問題來求解原問題,且對每個子問題只求解一次。
一般來說四個步驟
1.刻畫乙個最優結構特徵
2.遞迴的定義最優解值
3.計算最優解的值
4.利用計算出的資訊構造乙個最優解
這邊直接給出**
#include
#include
using
namespace std;
void
lis(
int arr,
int n)
ans =
max(dp[i]
, ans);}
cout <<
"最長上公升子串行的個數為:"
<< ans << endl;
}void
lds(
int arr,
int n)
ans =
max(dp[i]
, ans);}
cout <<
"最長下降子串行的個數為:"
<< ans << endl;
}int
main()
在求最長回文子串的時候我們用到了經典的「馬拉車」演算法
讓我們直接來看**
int
manacher()
max_len =
max(max_len, p[i]-1
);}return max_len;
}
子串行和子串是有區別的,乙個字串有許多子串行,比如字串cabbeaf,它的子串行有c、abb、e、a、f,可以通過刪除某些字元而變成回文字串,字串「cabbeaf」,刪掉『c』、『e』、『f』後剩下的子串「abba」就是回文字串,也是其中最長的回文子串行。注意和最長回文子串的區別,最長回文子串必須是連續的,這裡的最長回文子串行,可以是不連續的,這就是最長回文子串行lps問題
int
lps(
char
*str,
int n)
}return dp[0]
[n -1]
;//返回字串str[0...n-1]的最長回文子串行長度
}
顧名思義:區間dp就是在區間上進行動態規劃,求解一段區間上的最優解。主要是通過合併小區間的 最優解進而得出整個大區間上最優解的dp演算法。
既然讓我求解在乙個區間上的最優解,那麼我把這個區間分割成乙個個小區間,求解每個小區間的最優解,再合併小區間得到大區間即可。所以在**實現上,我可以列舉區間長度len為每次分割成的小區間長度(由短到長不斷合併),內層列舉該長度下可以的起點,自然終點也就明了了。然後在這個起點終點之間列舉分割點,求解這段小區間在某個分割點下的最優解。首先我們要列舉區間的長度,然後列舉區間的開始點,然後再列舉這個區間的分割點。
#include
#include
#include
#include
#define inf 0x3f3f3f3f
using
namespace std;
const
int maxn =
200+10;
int n;
int w[maxn]
, dp1[maxn]
[maxn]
, dp2[maxn]
[maxn]
;int
main()
for(
int i =
1; i <=
2* n; i++
) w[i]
= w[i]
+ w[i -1]
;//字首和
//開始列舉區間長度
//每次最少是2堆合併,所以最小值是2
for(
int x =
2; x <= n; x++
)for
(int l =
1; l + x -
1<
2* n; l++)}
int ans1 = inf, ans2 =
-inf;
//分別是最小值和最大值
for(
int i =
1; i <= n; i++
) cout << ans1 << endl << ans2 << endl;
system
("pause");
return0;
}
線性dp 區間dp
1 尼克的任務 額一道挺水的題,愣是做了幾個小時 動態規劃大致的思路還是找乙個轉移 換個詞就是影響 我們可以明顯看出本題的規則 空暇時,一遇到任務必須挑乙個接 求1 n時間內最大空暇時間 所以將任務排序是必要的,兩個關鍵字 再來想象一下當我做到第i 個任務時,我在 st i st i t i 1 時...
揹包練習及區間dp
這幾天學了區間dp,怎麼說呢,揹包還沒掌握好久又接受了新的知識,更懵逼了。有點跟不上老師上課的講課速度了,課下必須多看多做,不然真的不會做題了。哎,現在甚至有時候連題目都讀不懂什麼意思了,更別說思路了。崩潰了!區間dp,顧名思義,就是解決一些區間內的最優值的問題,一般和列舉結合運用,定義結構體什麼的...
區間dp小結
區間dp,顧名思義,就是在區間上dp,即把整個區間劃分為乙個個的小區間,在小區間內dp求出最優值,然後把這些小區間合併以後就是整個取件的最優值。下面是一些比較經典的區間dp題目 1.nyoj 737 石子合併 題意 有n堆石子,每堆有a i 個,每次合併時只能合併相鄰的兩堆,代價為兩堆石子的個數之和...