蓝桥杯数字三角形
數(shù)字三角形(進(jìn)階版)
問(wèn)題描述
(圖3.1-1)示出了一個(gè)數(shù)字三角形。 請(qǐng)編一個(gè)程序計(jì)算從頂至底的某處的一條路
徑,使該路徑所經(jīng)過(guò)的數(shù)字的總和最大。
●每一步可沿左斜線向下或右斜線向下走;
●1<三角形行數(shù)≤100;
●三角形中的數(shù)字為整數(shù)0,1,…99;
文件中首先讀到的是三角形的行數(shù)。
接下來(lái)描述整個(gè)三角形
輸出格式:
最大總和(整數(shù))
樣例輸入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
樣例輸出
30
1、首先我們考慮能否使用搜索去做,因?yàn)?strong>每一步可沿左斜線向下或右斜線向下走,也就是說(shuō)我們到達(dá)了一個(gè)位置(i,j),接著可以到達(dá)(i+1,j)或者(i+1,j+1);那么根據(jù)這個(gè)規(guī)律,就可以進(jìn)行遞歸搜索,代碼如下:
復(fù)雜度很明顯是2的n次方,時(shí)間很容易超限
原因分析如下:
當(dāng)我們要計(jì)算(i,j)這個(gè)位置時(shí),這個(gè)位置是由(i-1,j)轉(zhuǎn)移過(guò)來(lái)的,我們已經(jīng)求出了所有的(i.j)下面的位置,我們向上返回到(i-1,j)這個(gè)位置,我們向下就到達(dá)了(i,j+1)。我們發(fā)現(xiàn)(i,j)可以到達(dá)(i+1,j+1)并且(i,j+1)也可以到達(dá)(i+1,j+1)。那么(i+1,j+1)這個(gè)點(diǎn)我們就計(jì)算了兩次,會(huì)導(dǎo)致大量的重復(fù)計(jì)算,效率低下,導(dǎo)致時(shí)間超限。因此我們考慮,如果有一個(gè)數(shù)組用過(guò)來(lái)保存(i,j)能夠得到的最大值,那這樣我們就不用重復(fù)計(jì)算,那么就是把整個(gè)數(shù)組遍歷一遍,時(shí)間復(fù)雜度就是等差數(shù)組(n+1)*n/2,這樣時(shí)間復(fù)雜度就大大降低了。我們把這個(gè)方法叫做記憶化,這樣整個(gè)方法就叫做記憶化搜索。
接著優(yōu)化,因?yàn)檫f推要比遞歸快得多,因此平時(shí)我們要盡量將遞歸改造為遞推,我們之前f[i][j]表示的是從(i,j)出發(fā)能夠得到的最大的值,現(xiàn)在改造一下,將f[i][j]表示為從(1,1)出發(fā)到(i,j)能夠得到的最大的值。而這樣就能使用遞推,因?yàn)閒[i][j] 可以由f[i-1][j-1] 和f[i-1][j]得到,而這就是一個(gè)遞推式,因此當(dāng)我們計(jì)算(i,j)的時(shí)候只要保證(i-1,j-1)和(i-1,j)已經(jīng)計(jì)算并且保存就行。而這種形式我們采用的是從上到下的順推形式。代碼如下:
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <algorithm> #include <math.h> using namespace std; int val[101][101]; int f[101][101]; int n,ans; int main() {memset(f,0,sizeof(f));//初始化數(shù)組f cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){cin>>val[i][j];}} for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){if(j==1){f[i][j]=val[i][j]+f[i-1][j];}else if(j==n){f[i][j]=val[i][j]+f[i-1][j-1];}else f[i][j]=max(f[i-1][j-1],f[i-1][j])+val[i][j];}}for(int i=1;i<=n;i++){ans=max(ans,f[n][i]);}cout<<ans;return 0;}接著我們繼續(xù)優(yōu)化如果我們從上到下求最大值,轉(zhuǎn)化為從最后一排出發(fā)到達(dá)最后一層的最大值,那么對(duì)于(i,j)來(lái)說(shuō),可以從(i+1,j+1) (i+1,j)得到,那么我們就可以將整個(gè)遞推倒過(guò)來(lái)寫(xiě),省區(qū)最后的一個(gè)for循環(huán)
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <algorithm> #include <math.h> using namespace std; int val[101][101]; int f[101][101]; int n; int main() {memset(f,0,sizeof(f));cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){cin>>val[i][j];}} for(int i=n;i>=1;i--){for(int j=1;j<=i;j++){f[i][j]=max(f[i+1][j+1],f[i+1][j])+val[i][j];}}cout<<f[1][1];return 0; }總結(jié)
- 上一篇: rc52实现的部分代码
- 下一篇: D. Riverside Curio