luoguP1040 加分二叉树

在做各类DP的时候都要思路清晰!

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 30+9;
inline int read() {
	char ch = getchar(); int f = 1, x = 0;
	while(ch<'0' || ch>'9') {if(ch=='-') f = -1; ch = getchar();}
	while(ch>='0' && ch<='9') {x = (x<<1)+(x<<3)+(ch^48); ch = getchar();}
	return x*f;
} 

int n;
long long f[N][N];//f[i][j]: 序列以[i, j]范围内的点做子树时的最大分数
int root[N][N];//f[i][j]为最大分数时的子树[i, j]的根 

void pre() {
	n = read();
	for(int i = 1; i <= n; i++) f[i][i] = read(), f[i][i-1] = 1, root[i][i] = i;//下面的需要
        //因为这题是乘积,所以才初始化为1
	//同时给叶子节点初始化根 
}

void print_way(int l, int r) {
	if(l > r) return ;
	printf("%d ", root[l][r]);
	print_way(l, root[l][r]-1);
	print_way(root[l][r]+1, r);
}

void solve() {
	int j;
	for(int l = 2; l <= n; l++) {
		for(int i = 1; i+l-1 <= n; i++) {
			j = i+l-1;
			for(int k = i; k <= j; k++) {//逻辑上过的去,才会出答案 
				if(f[i][j] < f[i][k-1]*f[k+1][j]+f[k][k]) {
					f[i][j] = f[i][k-1]*f[k+1][j]+f[k][k];
					root[i][j] = k;
				}
			}
		}
	}
	printf("%lld
", f[1][n]);
	print_way(1, n);
}

int main() {
	pre();
	solve();
	return 0;
} 
原文地址:https://www.cnblogs.com/tyner/p/11746996.html