1. 程式人生 > >數字三角形問題(動態規劃)

數字三角形問題(動態規劃)

最近在刷動態規劃類的題,刷紫書的259頁題

題目來源:http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/1730.html

數字三角形問題

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic Discuss

Problem Description

給定一個由n行數字組成的數字三角形如下圖所示。試設計一個演算法,計算出從三角形的頂至底的一條路徑,使該路徑經過的數字總和最大。
 

 
對於給定的由n行數字組成的數字三角形,計算從三角形的頂至底的路徑經過的數字和的最大值。

Input

輸入資料的第1行是數字三角形的行數n,1≤n≤100。接下來n行是數字三角形各行中的數字。所有數字在0..99之間。

Output

輸出資料只有一個整數,表示計算出的最大值。

Sample Input

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

Sample Output

30

水題,直接貼程式碼了;有兩種方法,一個是遞推法,一個是記憶化搜尋法

遞推法:

#include<cstdio>
#include<Cstring>
#include<algorithm>
using namespace std;
int n;
int dp[105][105];
int a[105][105];
int dfs(int i,int j)
{
	if(dp[i][j]>=0) return dp[i][j];
	if(i==n) dp[i][j]=a[i][j];
	else dp[i][j]=a[i][j]+max(dfs(i+1,j),dfs(i+1,j+1));
	return dp[i][j];
}
int main()
{
	while(~scanf("%d",&n))
	{
		for(int i=1;i<=n;i++)
		for(int j=1;j<=i;j++)
		scanf("%d",&a[i][j]);
		memset(dp,-1,sizeof(dp));
		dfs(1,1);
		printf("%d\n",dp[1][1]);
	}
}

下面是記憶化搜尋法

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int dp[105][105]; 
int a[105][105];
int n;
int dfs(int i,int j)
{
	if(dp[i][j]>=0) return dp[i][j];
	
	if(i==n)  dp[i][j]=a[i][j];
	else	dp[i][j]=a[i][j]+max(dfs(i+1,j),dfs(i+1,j+1));
	
	return dp[i][j];
}
int main()
{
	while(~scanf("%d",&n))
	{
		memset(dp,-1,sizeof(dp));
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=i;j++)
			{
				scanf("%d",&a[i][j]);
			}
		}
		dfs(1,1);
		printf("%d\n",dp[1][1]);
	}
 } 

各自處理邊界的方法不同,遞推是先處理最底層的數然後往上推,遞迴加了一個if語句判斷是否到達邊界