1. 程式人生 > 其它 >《P1040 [NOIP2003 提高組] 加分二叉樹》

《P1040 [NOIP2003 提高組] 加分二叉樹》

$一開始一直在想怎麼構造出來的能更優,太傻了。$

$首先資料很小。然後就是有一個很顯然的結論。$

$因為是中序遍歷,如果以i為根,那麼比i小的肯定被分割到它的左子樹,比i大的肯定被分割到右子樹$

$有了這點我們可以dp去找最優的根,因為這裡顯然讓左右子樹的分都儘量大是最優的,所以滿足dp性,中間加個記憶化稍微優化一下就行。 $

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double
ld; typedef pair<int,int> pii; const int N = 1e6 + 5; const int M = 1e4 + 5; const LL Mod = 998244353; #define rep(at,am,as) for(int at = am;at <= as;++at) #define ref(at,am,as) for(int at = am;at >= as;--at) #define INF 1e9 #define dbg(ax) cout << "now this num is " << ax << endl; inline
long long ADD(long long x,long long y) { if(x + y < 0) return ((x + y) % Mod + Mod) % Mod; return (x + y) % Mod; } inline long long MUL(long long x,long long y) { if(x * y < 0) return ((x * y) % Mod + Mod) % Mod; return x * y % Mod; } inline long long DEC(long long x,long long y) {
if(x - y < 0) return (x - y + Mod) % Mod; return (x - y) % Mod; } int n,rt[35][35]; LL dp[35][35],val[35]; LL dfs(int L,int r) { if(L > r) return 1; if(L == r) { rt[L][r] = L; return dp[L][r] = val[L]; } if(dp[L][r] != -1) return dp[L][r]; rep(i,L,r) { LL ltmp = dfs(L,i - 1); LL rtmp = dfs(i + 1,r); if(ltmp * rtmp + val[i] > dp[L][r]) { dp[L][r] = ltmp * rtmp + val[i]; rt[L][r] = i; } } return dp[L][r]; } void dfs1(int L,int r) { if(L > r) return ; printf("%d ",rt[L][r]); dfs1(L,rt[L][r] - 1); dfs1(rt[L][r] + 1,r); } void solve() { memset(dp,-1,sizeof(dp)); scanf("%d",&n); rep(i,1,n) scanf("%d",&val[i]); dfs(1,n); printf("%lld\n",dp[1][n]); dfs1(1,n); } int main() { //int _; //for(scanf("%d",&_);_;_--) { solve(); //} system("pause"); return 0; }
View Code