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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

蓝桥杯数字三角形

發布時間:2023/12/8 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蓝桥杯数字三角形 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數字三角形(進階版)

問題描述
  (圖3.1-1)示出了一個數字三角形。 請編一個程序計算從頂至底的某處的一條路
  徑,使該路徑所經過的數字的總和最大。
  ●每一步可沿左斜線向下或右斜線向下走;
  ●1<三角形行數≤100;
  ●三角形中的數字為整數0,1,…99;

文件中首先讀到的是三角形的行數。
接下來描述整個三角形
輸出格式:
最大總和(整數)
樣例輸入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
樣例輸出
30
1、首先我們考慮能否使用搜索去做,因為每一步可沿左斜線向下或右斜線向下走,也就是說我們到達了一個位置(i,j),接著可以到達(i+1,j)或者(i+1,j+1);那么根據這個規律,就可以進行遞歸搜索,代碼如下:

#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為當前最大值 void dfs(int i,int j)//從(i,j)開始向下搜索 {if(i==n+1)//最后一行,終止條件{if(cnt>ans){ans=cnt;}return;}cnt+=val[i][j];//加上當前位置的數值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; }

復雜度很明顯是2的n次方,時間很容易超限
原因分析如下:
當我們要計算(i,j)這個位置時,這個位置是由(i-1,j)轉移過來的,我們已經求出了所有的(i.j)下面的位置,我們向上返回到(i-1,j)這個位置,我們向下就到達了(i,j+1)。我們發現(i,j)可以到達(i+1,j+1)并且(i,j+1)也可以到達(i+1,j+1)。那么(i+1,j+1)這個點我們就計算了兩次,會導致大量的重復計算,效率低下,導致時間超限。因此我們考慮,如果有一個數組用過來保存(i,j)能夠得到的最大值,那這樣我們就不用重復計算,那么就是把整個數組遍歷一遍,時間復雜度就是等差數組(n+1)*n/2,這樣時間復雜度就大大降低了。我們把這個方法叫做記憶化,這樣整個方法就叫做記憶化搜索。

#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));//初始化數組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; }

接著優化,因為遞推要比遞歸快得多,因此平時我們要盡量將遞歸改造為遞推,我們之前f[i][j]表示的是從(i,j)出發能夠得到的最大的值,現在改造一下,將f[i][j]表示為從(1,1)出發到(i,j)能夠得到的最大的值。而這樣就能使用遞推,因為f[i][j] 可以由f[i-1][j-1] 和f[i-1][j]得到,而這就是一個遞推式,因此當我們計算(i,j)的時候只要保證(i-1,j-1)和(i-1,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));//初始化數組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;}

接著我們繼續優化如果我們從上到下求最大值,轉化為從最后一排出發到達最后一層的最大值,那么對于(i,j)來說,可以從(i+1,j+1) (i+1,j)得到,那么我們就可以將整個遞推倒過來寫,省區最后的一個for循環

#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; }

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。