1. 程式人生 > >動態規劃經典五題

動態規劃經典五題

DP一年多沒碰過了,今天突然想找找感覺,找了經典的幾道DP複習著敲了敲。雖然最大子矩陣,滑雪,石子合併等問題也足夠經典,我還是從中找了5道最經典的DP寫了這篇博文,如果您是大一,大二想踏入程式競賽的同學可以當習題做做,如果您像我一樣不是ACMer,平時專案中也很少用DP,同樣可以回顧一下DP的奧妙。

1.最大連續子序列之和

給定K個整數的序列{ N1, N2, ..., NK },其任意連續子序列可表示為{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K。最大連續子序列是所有連續子序中元素和最大的一個, 例如給定序列{ -2, 11, -4, 13, -5, -2 },其最大連續子序列為{ 11, -4, 13 },最大和為20。

狀態轉移方程: sum[i]=max(sum[i-1]+a[i],a[i])

程式碼清單:

#include "stdio.h"

main(){
	int i,sum = 0, max = 0;
	int data[] = {
		1,-2,3,-1,7
	};
	for(i = 0; i < sizeof(data)/sizeof(data[0]); i++){
		sum += data[i];
		if(sum > max)
			max = sum;
		if(sum < 0)
			sum = 0;		
	}
	printf("%d",max);
}

2.數塔問題


數塔問題 :要求從頂層走到底層,若每一步只能走到相鄰的結點,則經過的結點的數字之和最大是多少?


轉移方程:sum[i] = max(a[左孩子] , a[右孩子]) + a[i]

#include "stdio.h"
#define N 5
main(){
	int i,j;
	int data[N][N] = {
			{9,0,0,0,0},
			{12,15,0,0,0},
			{10,6,8,0,0},
			{2,18,9,5,0},
			{19,7,10,4,16}
		};
		for(i = N-1; i > 0; i--)
			for(j = 0; j < i; j++)
				data[i-1][j] += data[i][j] > data[i][j+1] ? data[i][j] : data[i][j+1];
		
		printf("%d",data[0][0]);
		
		
}

3.01揹包問題

N件物品和一個容量為V的揹包。第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使價值總和最大。

轉移方程:dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]] + value[i]

#include "stdio.h"
#define max(a,b) ((a)>(b)?(a):(b))



main(){
	
	int v = 10 ;  
	int n = 5 ;    
	 
 	int value[] = {0, 8 , 10 , 4 , 5 , 5};     
	int weight[] = {0, 6 , 4 , 2 , 4 , 3};   
	int i,j;    
	int dp[n+1][v+1];
	for(i = 0; i < n+1; i++)
		for(j = 0; j < v+1; j++)
			dp[i][j] = 0;


	for(i = 1; i <= n; i++){
		for(j = 1; j <= v; j++){
			if(j >= weight[i])
				dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]] + value[i]);
			else
				dp[i][j] = dp[i-1][j];
		}
	}

	printf("%d",dp[n][v]);
}

4.最長遞增子序列(LIS)

給定一個序列 An a1 ,a2 ,  ... , an ,找出最長的子序列使得對所有 j ,ai aj 

轉移方程:b[k]=max(max(b[j]|a[j]<a[k],j<k)+1,1);

程式碼清單:

#include "stdio.h"

main(){
	int i,j,length,max=0;
	int a[] = {
		1,-1,2,-3,4,-5,6,-7
	};
	int *b;
	b = (int *)malloc(sizeof(a));
	length = sizeof(a)/sizeof(a[0]);

	for(i = 0; i < length; i++){
		b[i] = 1;
		for(j = 0; j < i; j++){
			if(a[i] > a[j] && b[i] <= b[j]){
				b[i] = b[j] + 1;
			}
		}
	}
	for(i = 0; i < length; i++)
		if(b[i] > max)
			max = b[i];
		
	printf("%d",max);
}

5.最長公共子序列(LCS)

一個序列 S ,如果分別是兩個或多個已知序列的子序列,且是所有符合此條件序列中最長的,則 S 稱為已知序列的最長公共子序列。

轉移方程:

dp[i,j] = 0                                          i=0 || j=0

dp[i,j] = dp[i-1][j-1]+1                        i>0,j>0, a[i] = b[j]       

dp[i,j] = max(dp[i-1][j],dp[i][j-1])        i>0,j>0, a[i] != b[j]

#include "stdio.h"
#define M 8
#define N 6

		
void printLSC(int i, int j,char *a, int status[][N]){
	if(i == 0 || j== 0)
		return;
	if(status[i][j] == 0){
		printLSC(i-1,j-1,a,status);
		printf("%c",a[i]);
	}else{
		if(status[i][j] == 1)
			printLSC(i-1,j,a,status);
		else
			printLSC(i,j-1,a,status);
	}
}
main(){
	int i,j;

	char a[] = {' ','A','B','C','B','D','A','B'};
	char b[] = {' ','B','D','C','B','A'};
	int status[M][N]; //儲存狀態
	int dp[M][N];

	for(i = 0; i < M; i++)
		for(j = 0; j < N; j++){
			dp[i][j] = 0;
			status[i][j] = 0;
		}
			
	for(i = 1; i < M; i++)
		for(j = 1; j < N; j++){
			if(a[i] == b[j]){
				dp[i][j] = dp[i-1][j-1] + 1;
				status[i][j] = 0;
			}
			else if(dp[i][j-1] >= dp[i-1][j]){
				dp[i][j] = dp[i][j-1];
				status[i][j] = 2;
			}
			else{
				dp[i][j] = dp[i-1][j];
				status[i][j] = 1;
			}
				
				
		}
	printf("最大長度:%d",dp[M-1][N-1]);
	printf("\n");
	printLSC(M-1,N-1,a,status);
	printf("\n");

}

==================================================================================================

  作者:nash_  歡迎轉載,與人分享是進步的源泉!

===================================================================================================

相關推薦

動態規劃經典

DP一年多沒碰過了,今天突然想找找感覺,找了經典的幾道DP複習著敲了敲。雖然最大子矩陣,滑雪,石子合併等問題也足夠經典,我還是從中找了5道最經典的DP寫了這篇博文,如果您是大一,大二想踏入程式競賽的同學可以當習題做做,如果您像我一樣不是ACMer,平時專案中也很少用DP,同

動態規劃經典教學,上過《算導》的應該都會

本文始發於個人公眾號:**TechFlow**,原創不易,求個關注 今天是LeetCode專題第41篇文章,我們一起來看一道經典的動態規劃問題Edit Distance,編輯距離。 今天這道題我本來是想跳過的,因為它實在是太經典了,屬於典型的老掉牙問題了。但是想了想,一方面因為之前立了flag要把所有M

LintCode 125: Backpack II (動態規劃經典: 0-1揹包問題)

解法1: 經典DP解法。 時間複雜度O(MN),空間複雜度O(MN)。 注意:dp[m+1][n+1],如果定義成dp[m][n],dp[0][]就有歧義:到底表示不取任何包,還是取包0呢? class

nyist oj 17 單調遞增最長子序列 (動態規劃經典

單調遞增最長子序列 時間限制:3000 ms  |  記憶體限制:65535 KB 難度:4 描述求一個字串的最長遞增子序列的長度 如:dabdbf最長遞增子序列就是abdf,長度為4

《面試--動態規劃》 ---經典的演算法問題

一 動態規劃 動態規劃問題是面試題中的熱門話題,如果要求一個問題的最優解(通常是最大值或者最小值),而且該問題能夠分解成若干個子問題,並且小問題之間也存在重疊的子問題,則考慮採用動態規劃。 使用動態規劃特徵: 1. 求一個問題的最優解 2. 大問題可以分

合併石子(動態規劃經典

步驟: 1. 設狀態:f[i][j]表示從第i堆合併到第j堆,合併成一堆的最小得分 2. 初始狀態:f[i][i]=0;     最終狀態:f[1][n];//從第1堆合併到第n堆的最小得分 3.狀態轉移方程:f[i][j]=max(f[i][j],f[i][k]+f[k+

基於python的動態規劃經典問題(爬樓梯,取珠寶,最大子序列和,找零錢)

1,爬樓梯問題 一個人爬樓梯,每次只能爬1個或兩個臺階,假設有n個臺階,那麼這個人有多少種不同的爬樓梯方法 動態規劃的狀態轉移:第 i 個狀態的方案數和第 i-1, i-2時候的狀態有關,即:dp[i]=dp[i-1]+dp[i-2],dp表示狀態矩陣。 def climb_stai

動態規劃的一道(室友約稿)

題目:輸入一個無序的陣列(值都大於等於0),給定一個值sum,從陣列中取出任意個數的值,使得這些值的和為sum。 輸出有多少個這樣的組合? 輸入格式:第一行,為陣列長度和sum 第二行,為陣列 這題為動態規劃的一道題,先補充一下關於動態規劃的基本概念 動態規劃

DP動態規劃專題 :LeetCode 140. Word Break II

LeetCode 140. Word Break II Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to constr

最大連續子序列和:動態規劃經典題目(2)

問題描述:       連續子序列最大和,其實就是求一個序列中連續的子序列中元素和最大的那個。       比如例如給定序列:            { -2, 11, -4, 13, -5, -2 }         其最大連續子序列為{

動態規劃經典問題切鋼條

package 小米oj; public class 鋼條切割 { public static void main(String[] args) { int price[] = {1,5,8,9,10,17,17,20,24,30}; Syste

最大連續子序列——動態規劃經典問題

前幾天在牛客網上看到一道關於動態規劃的題目,完全不知如何著手。所以就去學習了一下動態規劃,參考網上的解析,跌跌撞撞把一道杭電上的最大連續子序列敲了出來。 題目來源: http://acm.hdu.edu.cn/showproblem.php?pid=1231 給定K個整數的

動態規劃經典題目總結

在演算法中,動態規劃題目算是比較經典的一類題目。在找工作中,不管是筆試,還是面試,我們經常會遇到用動態規劃來解決問題的情況,有時候面試官還需要我們現場手寫出動態規劃解法的程式碼。因此,在求職中能靈活的運用動態規劃就相當重要了。下面我總結出了一些經典的動態規劃題目,其中有些還是面試中遇到的。

動態規劃經典——石子歸併

1.鏈式歸併 問題描述 設有N堆沙子排成一排,其編號為1,2,3,…,N(N<=100)。每堆沙子有一定的數量。現要將N堆沙子併成為一堆。歸併的過程只能每次將相鄰的兩堆沙子堆成一堆,這樣經過N-1次歸併後成為一堆。找出一種合理的歸併方法,使總的代價最小。 【輸入格式

POJ 1088 滑雪(動態規劃經典

滑雪 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 63875 Accepted: 23387 Description Michael喜歡滑雪百這並不奇怪, 因為滑雪的確很刺激。可是為了獲得速度

動態規劃經典最優子結構總結

(1)0-1揹包: 如果有一個揹包,總載重量為Wt,有n個物品,每個物品重Wi,每個物品價值Ci,那麼如何裝才能讓這個包裡面東西的價值最高? dp[i][j]為前i個物品當中選擇裝進一個載重量為j的包裡最大價值,則: 初始化:dp【0】【x】=0;for i=0-》n;j=

編輯距離(動態規劃經典

1183 編輯距離 編輯距離,又稱Levenshtein距離(也叫做Edit Distance),是指兩個字串之間,由一個轉成另一個所需的最少編輯操作次數。許可的編輯操作包括將一個字元替換成另一個字元

Leetcode 120. Triangle 三角形問題(動態規劃經典) 解題報告

1 解題報告 首先我承認我很二哈,這道題我明明已經做過了,但是剛剛不知道為什麼又去做了一遍,而且我查了下兩次的解法還有所差別(貌似是現在的版本有進步了呢) 問題就是一個三角形的陣列,求從頂部到下方的最短路徑。。 這個問題是太過經典+Easy的DP問題了,哈

動態規劃經典——最長公共子序列

最長公共子序列 時間限制:3000 ms | 記憶體限制:65535 KB 難度:3 描述 咱們就不拐彎抹角了,如題,需要你做的就是寫一個程式,得出最長公共子序列。

自己動態規劃的第一,數字三角形

1087: 三角形 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 72  Solved: 40 [Submit][Status][BBS] Des