1. 程式人生 > >【簡單】動態規劃數字三角形

【簡單】動態規劃數字三角形

例題一:數字三角形(POJ1163)

The Triangle

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 8321 Accepted: 35029

Description

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

(Figure 1)

Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left or diagonally down to the right.

Input

Your program is to read from standard input. The first line contains one integer N: the number of rows in the triangle. The following N lines describe the data of the triangle. The number of rows in the triangle is > 1 but <= 100. The numbers in the triangle, all integers, are between 0 and 99.

Output

Your program is to write to standard output. The highest sum is written as an integer.

Sample Input

5//三角形行數,下面是三角形
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

Sample Output

30

題意:在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或右下走,比如數字3只可以走到8和1,只需求出這個最大和即可,不必給出具體路徑

三角形的行數小於等於100,數字為0-99

數字之和int就能放得下

思路:這道題看上去可以用遞迴,D(r,j) 第r行第j個數字,從1開始。maxsum(i,j)是從d(i,j)到底邊的各條路徑中,最佳路徑之和,從D(i,j)出發,只有兩條路D(i+1,j)和D(i+1,j+1),故可以寫出遞推式

if(r==N)

maxsum(r,j)=D(i,j)

else

maxsum(r,j)=max(maxsum(r+1,j),maxsum(r+1,j+1))+D(i,j)

這樣看上去是不是很簡單,但是這樣做提交到OJ會超時,如果採用遞迴的方法,深度遍歷每條路徑,每個數字的maxsum(i,j)可能會被計算多次,存在大量重複計算,則時間複雜度為2^n.對於n=100行,肯定超時。

故此題應該用動態規劃,每算出一個maxsum(i,j)就儲存起來,下次用到其值時直接取用,則可免去重複計算,那麼可以用         O(n^2)時間完成計算,因為三角形的數字總數是n(n+1)/2,每個數字都要算一次maxsum(i,j)

程式碼如下

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
const int N=1000;
int maxsum[N][N];
int d[N][N];
int n;
using namespace std;
int Maxsum(int i,int j)
{
    if(maxsum[i][j]!=-1)
        return maxsum[i][j];//已經計算過maxsum的值,不需要再計算,避免了重複計算
    if(n==1)
        return d[i][j];
    else
    {
        maxsum[i][j]=max(Maxsum(i+1,j),Maxsum(i+1,j+1))+d[i][j];
    }
    return maxsum[i][j];
}
int main()
{

    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            cin>>d[i][j];
            maxsum[i][j]=-1;

        }
    }

    cout<<Maxsum(1,1);
    return 0;
}