树的问题 要么就是递归 要么就是左右子树分治
最优问题 想到最优子结构 动态规划
如何使用动态规划做出这道题
首先找最优子结构
只有数值小于等于两个节点时 不用考虑 直接为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}; } }