1. 程式人生 > >數字三角形(C語言)

數字三角形(C語言)

一、問題描述
給定一個由行數字組成的數字三角形。試著設計一個演算法,計算出從三角形的頂到底的一條路徑,使得該路徑經過的數字總和最大,並分析演算法的計算複雜性。如下圖所示:
7
3 8
8 1 0
   2 7 4 4
   4 5 2 6 5

二、問題分析及演算法描述(包含主要變數和函式功能介紹)
設a(i,j)表示數字三角形中的第i行第j個點。 max[i][j]表示第i行第j個數字到低端的最佳路徑之和,則原問題的解就是max[1][1]的值了。 從a(i,j)這個點向下走,顯然只能走a(i+1,j)和a(i+1,j+1)這兩個點了。而max[i][j]的最優值=a(i,j)的值+max{. max[i+1][j],max[i+1][j+1] }o 所以,我們可以至底向,上來計算。先計算最後一層的點的,然後倒二層的,…一直算到第一層。
遞推方程:

三、源程式及程式說明檔案

#include "stdafx.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
using namespace std;-·
int a[110][110];
int max[110][110];
int n;
int MaxSum(int n)
{
    for (int i = n; i >= 1; i--)
{
    max[n][i] = a[n][i];//初始化,最下面一層的max陣列就是三角形最下面一層的值
} for (int i = n - 1; i >= 1; i--) {//從倒數第二層向上計算 for (int j = 1; j <= i; j++) {//計算第 i 層的每一個點的 max[][] if (max[i + 1][j + 1]>max[i + 1][j]) { max[i][j] = max[i + 1][j + 1] + a[i][j];//要麼向下一層上和它最近的右邊走 } else max[i][j] = max[i + 1][j] + a[i][j];//要麼向下一層上和它最近的左邊走 } } return max[1
][1]; } int main() { cin >> n; for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { cin >> a[i][j]; } }//構造數字三角形 cout << MaxSum(n) << endl; int k = 1; for (int i = k; i <= n; i++) { cout << a[i][k] << " "; if (max[i + 1][k + 1] + a[i][k] > max[i + 1][k] + a[i][k]) { k = k + 1; } }//列印路徑 return 0; } 四.證明數字三角形的最優子結構性質。 證: 原問題:MAX[i,j] 最優解 L[n] 子問題:MAX[i+1,j+1] 最優解 L’[n] 反證法:設L’[n] 不為子問題的最優解,令M’[n]為子問題的最優解 則M’[n]<L’[n] 所以 M’[n]+L[n-1]<L’[n]+L[n-1]=L[n]L[n]為原問題的最優解相矛盾,即證! 五、答案顯示 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 30 7 3 8 7 5

六、演算法分析(T(n)和S(n))
本程式為遞推型動歸程式,由底向上遞推,除最後一行外,每一行的每個點
最頂部即為所求。其三角形的數字總和為 n(n + 1)/2,演算法的時間複雜度 T(n) = O(n^2),空間複雜度與n成線性比例關係,即其空間複雜度 S(n) = O(n);
七、課程設計總結
通過本次課程設計和實際操作,對於動態規劃有了更好的的理解,尤其是對最優子結構的認識更加深刻,從中學到了許多新的程式設計思想。知道了如何更好地設計演算法很大的提高了程式設計效率。
在解決本次題目—數字三角形中出現了一些因為粗心而出現的問題,經過小組討論和一反除錯最終將所有問題解決。實驗的成功離不開小組三人的合作以及老師的指導,本次試驗不僅在演算法問題上收穫頗豐,並且因為小組三人的通力協作,加深了對此次問題的理解和學習。