树的问题 要么就是递归 要么就是左右子树分治
最优问题 想到最优子结构 动态规划
如何使用动态规划做出这道题
首先找最优子结构
只有数值小于等于两个节点时 不用考虑 直接为a*b
考虑简单的情况 1,2,3
可能有三种情况 要依次遍历
1为根 1*2 + 1*3
2为根 1*2 + 2*3
3为根 1*3 + 3*2
选择根节点,分别计算出每个根节点的最优值 然后选出最优的
所以对于有很多值的
把每个点都作为根节点 然后左右子树分治 分别求出最优解
定义 转移状态
首先 有一个范围 l,r
然后dp[l,r]表示 遍历i属于[l,r] 以i为根节点的所代表的最小值
min(dp(l,i-1) + im + in + dp(i+1,r))
m 代表dp(l,i-1) 最优选出的 根节点
n 代表 dp(i+1,r)最优选出的 根节点
所以根节点应该把两个值中较小的值放到根节点
package test;
import java.util.Scanner;
import java.util.*;
import java.io.*;
public class Main{
private static int[] seq;
public static void main(String[] args) {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
int n = sc.nextInt();
seq = new int[n+1];
for(int i=0;i<n;i++){
seq[i] = sc.nextInt();
}
seq[n] = Integer.MAX_VALUE;
int res = dp(0,n-1)[0];
System.out.println(res);
}
public static int[] dp(int l, int r){
//res[0] 该序列最小值 res[1] 最小值对应的根节点
if(l == r) return new int[]{0,l};
if(l+1 == r){
return new int[]{seq[l]*seq[r],l};
}
int res_0 = Integer.MAX_VALUE;
int res_1 = seq.length-1;
for(int i=l; i<=r ;i++){
if(i==l){
int[] VandN = dp(i+1,r);
int temp = VandN[0] + seq[i]*seq[VandN[1]];
if(temp <= res_0) {res_0 = temp; res_1 = seq[res_1]>seq[i]?i:res_1;}
}else
if(i==r){
int[] VandN = dp(l,i-1);
int temp = VandN[0] + seq[i]*seq[VandN[1]];
if(temp <= res_0) {res_0 = temp; res_1 = seq[res_1]>seq[i]?i:res_1;}
}else{
int[] lVandN = dp(l,i-1);
int[] rVandN = dp(i+1,r);
int temp = lVandN[0] + seq[i]*seq[lVandN[1]] + seq[i]*seq[rVandN[1]] + rVandN[0];
if(temp <= res_0) {res_0 = temp; res_1 = seq[res_1]>seq[i]?i:res_1;}
}
}
return new int[]{res_0,res_1};
}
}



京公网安备 11010502036488号