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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【树形区间DP】加分二叉树(ssl 1033/luogu 1040)

發布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【树形区间DP】加分二叉树(ssl 1033/luogu 1040) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

加分二叉樹

ssl 1033

luogu 1040

題目大意:

有一棵中序遍歷為1,2,3…n的二叉樹(當然二叉樹的樣子沒有固定),現在給出每個節點的分數,一個節點的加數=兩個子節點的加數相乘+當前節點的分數(空的子節點加數為1,葉子節點加數為它的分數),現在要你求最大的加數

輸入樣例

5 5 7 1 2 10

輸出樣例

145 3 1 2 4 5

數據范圍

n<30n<30n<30
Ans?4,000,000,000Ans \leqslant 4,000,000,000Ans?4,000,000,000

解題思路:

f[i][j]f[i][j]f[i][j]為中序遍歷為i~j的子樹的最大加數,然后每次枚舉中間點去劃分樹,然后DP即可

代碼:

#include<cstdio> #define max(a,b) (a)>(b)?(a):(b) using namespace std; long long n,a[50],f[50][50],s[50][50]; void dg(long long l,long long r)//遞歸輸出前序遍歷 {if (l>r) return;printf("%lld ",s[l][r]);dg(l,s[l][r]-1);dg(s[l][r]+1,r); } int main() {scanf("%lld",&n);for(int i=1;i<=n;++i){f[i][i-1]=1;//處理空子樹的情況f[i+1][i]=1;scanf("%lld",&a[i]);f[i][i]=a[i];s[i][i]=i; }for(int i=n-1;i>0;--i)//倒著枚舉可以先做小的再做大的for(int j=i+1;j<=n;++j)//枚舉范圍for(int k=i;k<=j;++k)//中間點if (f[i][k-1]*f[k+1][j]+a[k]>f[i][j]){f[i][j]=f[i][k-1]*f[k+1][j]+a[k];//DPs[i][j]=k;}printf("%lld\n",f[1][n]);dg(1,n); }

總結

以上是生活随笔為你收集整理的【树形区间DP】加分二叉树(ssl 1033/luogu 1040)的全部內容,希望文章能夠幫你解決所遇到的問題。

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