小团有一个由N个节点组成的二叉树,每个节点有一个权值。定义二叉树每条边的开销为其两端节点权值的乘积,二叉树的总开销即每条边的开销之和。小团按照二叉树的中序遍历依次记录下每个节点的权值,即他记录下了N个数,第i个数表示位于中序遍历第i个位置的节点的权值。之后由于某种原因,小团遗忘了二叉树的具体结构。在所有可能的二叉树中,总开销最小的二叉树被称为最优二叉树。现在,小团请小美求出最优二叉树的总开销。
小团有一个由N个节点组成的二叉树,每个节点有一个权值。定义二叉树每条边的开销为其两端节点权值的乘积,二叉树的总开销即每条边的开销之和。小团按照二叉树的中序遍历依次记录下每个节点的权值,即他记录下了N个数,第i个数表示位于中序遍历第i个位置的节点的权值。之后由于某种原因,小团遗忘了二叉树的具体结构。在所有可能的二叉树中,总开销最小的二叉树被称为最优二叉树。现在,小团请小美求出最优二叉树的总开销。
第一行输入一个整数N(1<=N<=300),表示二叉树的节点数。
第二行输入N个由空格隔开的整数,表示按中序遍历记录下的各个节点的权值,所有权值均为不超过1000的正整数。
输出一个整数,表示最优二叉树的总开销。
5 7 6 5 1 3
45
最优二叉树如图所示,总开销为7*1+6*5+5*1+1*3=45。
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int[] a = new int[n + 2]; for (int i = 1; i <= n; i++) { a[i] = in.nextInt(); } int[][][] f = new int[n + 2][n + 2][2]; for (int i = n; i >= 1; i--) { f[i][i][0] = a[i] * a[i + 1]; f[i][i][1] = a[i] * a[i - 1]; for (int j = i + 1; j <= n; j++) { f[i][j][0] = Integer.MAX_VALUE; f[i][j][1] = Integer.MAX_VALUE; for (int k = i; k <= j; k++) { f[i][j][0] = Math.min(f[i][j][0], a[k] * a[j + 1] + f[i][k - 1][0] + f[k + 1][j][1]); f[i][j][1] = Math.min(f[i][j][1], a[k] * a[i - 1] + f[i][k - 1][0] + f[k + 1][j][1]); } } } System.out.println(f[1][n][0]); } }
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = sc.nextInt(); int[] nums = new int[n + 1]; for (int i = 0; i < n; i++) { nums[i] = sc.nextInt(); } Main main = new Main(); int ans = Integer.MAX_VALUE; int[][][] memo = new int[n + 1][n + 1][n + 1]; for (int i = 0; i < n; i++) { ans = Math.min(ans,main.dfs(nums,0,i - 1,i,memo) + main.dfs(nums,i + 1,n - 1,i,memo)); } System.out.println(ans); } } int dfs(int[] nums, int l, int r, int father, int[][][] memo) { if (l > r) return 0; if (l == r) return nums[l] * nums[father]; if (memo[l][r][father] != 0) return memo[l][r][father]; int res = Integer.MAX_VALUE; for (int i = l; i <= r; i++) { int left = dfs(nums, l, i - 1, i, memo); int right = dfs(nums, i + 1, r, i, memo); res = Math.min(res, left + right + nums[i] * nums[father]); } memo[l][r][father] = res; return res; } }