求第一層到最後一層的路徑,將該路徑上的所有數字相加後得到的和最大是多少。
#include
using
namespace std;
const
int maxn =
1000
;int f[maxn]
[maxn]
, dp[maxn]
[maxn]
;int
main()
}for
(int i =
1; i <= n; i++
)for
(int i = n -
1; i >=
0; i--)}
cout << dp[1]
[1]<< endl;
//dp[1][1]即為答案
return0;
}
對於數塔問題,貪心法從最上層開始,每次選擇坐下和右下兩個數字中較大的乙個,一直到最底層得到最後結果,顯然這不一定可以得到最優解。然而動態規劃不管是採用自底向上還是自頂向下,都是從邊界開始向上得到目標問題的解。
動態規劃總是會考慮所有子問題,並選擇繼承能得到最優結果的那個,對暫時沒被繼承的子問題,由於重疊子問題的存在,後期可能會再次考慮它們,因此還有機會成為全域性最優的那一部分。
貪心是一種壯士割腕的決策,只要進行了選擇,就不後悔;動態規劃則要看哪個選擇笑到了最後,暫時的領先說明不了什麼。
給定乙個數字序列a1, a2, a3, … , an。求i,j ( 1 <= i <= j <= n ),使得ai + … + aj 最大, 輸出這個最大和。
#include
using
namespace std;
const
int maxn =
10010
;int a[maxn]
, dp[maxn]
;int
main()
dp[0]
= a[0]
; ans =0;
//dp[i]存放以a[i]結尾的連續序列的最大和,需要遍歷i得到最大的才是結果。
for(
int i =
1; i < n; i++)
cout << ans << endl;
return0;
}
在乙個數字序列中,找到乙個最長的子串行(可以不連續),使得這個子串行是不下降(非遞減)的。
#include
using
namespace std;
const
int maxn =
10010
;int a[maxn]
, dp[maxn]
;int
main()
ans =0;
//記錄最大的dp[i]
for(
int i =
1; i <= n; i++)}
ans =
max(dp[i]
, ans);}
cout << ans << endl;
return0;
}
給定兩個字串(或數字序列)a和b,求乙個字串,使得這個字串是a和b的最長公共部分(子串行可以不連線)。
#include
using
namespace std;
const
int maxn =
10010
;string a, b;
int dp[maxn]
[maxn]
;int
main()
for(
int i =
0; i <= b.
length()
; i++
)for
(int i =
1; i <= a.
length()
; i++
)else}}
cout << dp[a.
length()
][b.
length()
];return0;
}
動態規劃經典例子
金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說 你的房間需要購買哪些物品,怎麼布置,你說了算,只要不超過n元錢就行 今天一早金明就開始做預算,但是他想買的東西太多了,肯定會超過媽媽限定的n元。於是,他把每件物品規定了乙個重要度,分為5...
動態規劃經典例子
總公司擁有高效裝置m臺,準備分給下屬的n個分公司。各分公司若獲得這些裝置,可以為國家提供一定的盈利。問 如何分配這m臺裝置才能使國家得到的盈利最大?求出最大盈利值。其中m 15,n 10。分配原則 每個公司有權獲得任意數目的裝置,但總台數不超過裝置數m。輸入格式 第一行有兩個數,第乙個數是分公司數n...
動態規劃例子
對於由從1到n 1 n 39 這n個連續的整數組成的集合來說,我們有時可以將集合分成兩個部分和相同的子集合。例如,n 3時,可以將集合 分為和。此時稱有一種方式 即與順序無關 n 7時,共有四種方式可以將集合 分為兩個部分和相同的子集合 和 和 和 和 輸入 程式從標準輸入讀入資料,只有一組測試用例...