日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

蓝桥杯数字三角形

發(fā)布時(shí)間:2023/12/8 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蓝桥杯数字三角形 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

數(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)行遞歸搜索,代碼如下:

#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <algorithm> #include <math.h> using namespace std; int val[101][101]; int n,ans,cnt;//ans位搜索的最大值,cnt為當(dāng)前最大值 void dfs(int i,int j)//從(i,j)開(kāi)始向下搜索 {if(i==n+1)//最后一行,終止條件{if(cnt>ans){ans=cnt;}return;}cnt+=val[i][j];//加上當(dāng)前位置的數(shù)值dfs(i+1,j);dfs(i+1,j+1);cnt-=val[i][j]; } int main() {cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){cin>>val[i][j];}} dfs(1,1);cout<<ans;return 0; }

復(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è)方法就叫做記憶化搜索。

#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,cnt; int dfs(int i,int j) {if(f[i][j]!=-1) {return f[i][j];}if(i==n+1){return f[i][j]=val[i][j];}return f[i][j]=max(dfs(i+1,j+1),dfs(i+1,j))+val[i][j]; } int main() {memset(f,-1,sizeof(f));//初始化數(shù)組f cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=i;j++){cin>>val[i][j];}}cout<<dfs(1,1);return 0; }

接著優(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é)

以上是生活随笔為你收集整理的蓝桥杯数字三角形的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。