設乙個nn個節點的二叉樹tree的中序遍歷為(1,2,3,…,n1,2,3,…,n),其中數字1,2,3,…,n1,2,3,…,n為節點編號。每個節點都有乙個分數(均為正整數),記第ii個節點的分數為di,treedi,tree及它的每個子樹都有乙個加分,任一棵子樹subtreesubtree(也包含treetree本身)的加分計算方法如下:
subtreesubtree的左子樹的加分× subtreesubtree的右子樹的加分+subtreesubtree的根的分數。
若某個子樹為空,規定其加分為11,葉子的加分就是葉節點本身的分數。不考慮它的空子樹。
試求一棵符合中序遍歷為(1,2,3,…,n1,2,3,…,n)且加分最高的二叉樹treetree。要求輸出;
(1)treetree的最高加分
(2)treetree的前序遍歷
輸入格式:
第11行:11個整數n(n<30)n(n<30),為節點個數。
第22行:nn個用空格隔開的整數,為每個節點的分數(分數<100<100)。
輸出格式:
第11行:11個整數,為最高加分(ans \le 4,000,000,000≤4,000,000,000)。
第22行:nn個用空格隔開的整數,為該樹的前序遍歷。
輸入樣例#1: 複製
5輸出樣例#1: 複製5 7 1 2 10
145view code3 1 2 4 5
難以下手 看到是dfs專題一直想著用dfs來解
這題用區間dp很方便能解
f(i,j)=*f+頂點i的分數 (i
#includeusing
namespace
std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);i--)
#define ri(n) scanf("%d",&(n))
#define rii(n,m) scanf("%d%d",&n,&m)
#define riii(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define rs(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define fi first
#define rep(i,n) for(int i=0;i
#define clr(a,v) memset(a,v,sizeof a)
/////////////////////////////////
//#define inf 0x3f3f3f3f
#define n 100
introot[n][n];
ll dp[n][n];
intn;
intfirst;
ll search1(
int l,int r)//
區間記憶化dp}}
return
dp[l][r];
}void print(int l,int
r)int
main()
cout
<1,n)<
first=1
; print(
1,n);
}
非記憶化
#includeusingview codenamespace
std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);i--)
#define ri(n) scanf("%d",&(n))
#define rii(n,m) scanf("%d%d",&n,&m)
#define riii(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define rs(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define fi first
#define rep(i,n) for(int i=0;i
#define clr(a,v) memset(a,v,sizeof a)
/////////////////////////////////
//#define inf 0x3f3f3f3f
#define n 100
introot[n][n];
ll dp[n][n];
intn;
intfirst;
void print(int l,int
r)int
main()
rep(len,
1,n)
rep(i,
1,n)
}cout
<1][n]<
first=1
; print(
1,n);
}
更加簡潔
#include#includeview codeusing
namespace
std;
int n,v[39],f[47][47],i,j,k,root[49][49
];void print(int l,int
r) printf(
"%d
",root[l][r]);
print(l,root[l][r]-1
); print(root[l][r]+1
,r);
}int
main()
for(i=n; i>=1; i--)
for(j=i+1; j<=n; j++)
for(k=i; k<=j; k++)
}printf(
"%d\n
",f[1
][n]);
print(
1,n);
return0;
}
P1040 加分二叉樹
設乙個n個節點的二叉樹tree的中序遍歷為 1,2,3,n 其中數字1,2,3,n為節點編號。每個節點都有乙個分數 均為正整數 記第i個節點的分數為di,tree及它的每個子樹都有乙個加分,任一棵子樹subtree 也包含tree本身 的加分計算方法如下 subtree的左子樹的加分 subtree...
P1040 加分二叉樹
設乙個nn個節點的二叉樹tree的中序遍歷為 1,2,3,n1,2,3,n 其中數字1,2,3,n1,2,3,n為節點編號。每個節點都有乙個分數 均為正整數 記第ii個節點的分數為di,treedi,tree及它的每個子樹都有乙個加分,任一棵子樹subtreesubtree 也包含treetree本...
P1040 加分二叉樹
題目 很明顯的一道區間dp題目。和acwing上的金字塔有點像。表面上感覺是樹形dp,實則不然。題中給出的1 n是中序遍歷,按照區間dp的套路 設f l r 為中序遍歷是l r的子樹的最大加分值。那麼劃分點佷顯然就是列舉一顆子樹的根節點,再加上這棵樹是一顆二叉樹就更好辦了。dp方程如下 for in...