有 N 堆金币排成一排,第 i 堆中有 C[i] 块金币。每次合并都会将相邻的两堆金币合并为一堆,成本为这两堆金币块数之和。经过N-1次合并,最终将所有金币合并为一堆。请找出将金币合并为一堆的最低成本。
其中,1 <= N <= 30,1 <= C[i] <= 100
输入描述:
第一行输入一个数字 N 表示有 N 堆金币
第二行输入 N 个数字表示每堆金币的数量 C[i]
输出描述:
输出一个数字 S 表示最小的合并成一堆的成本
输入例子1:
4
3 2 4 1
输出例子1:
20
输出说明:
1.先将2和3合并,成本为num=5,剩余金币为 5 4 1。
2.将1 和4合并,成本为num=5+5=10,剩余金币为 5 5。
3.将最后两堆合并,成本num=10+5+5=20。
思路: 使用动态规划,用dp[j] [j]
表示i
堆到j
堆的最优合并后的成本,那么我们只要找到k
,i<=k<j
,使得
dp[i][j]=dp[i][k]+dp[k+1][j]+sum[i][j]
取到最小值即可。
i==j
时,dp[i][j]=0
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int N =sc.nextInt();
int[] arr=new int[N];
for(int i=0;i<N;i++)
arr[i]=sc.nextInt();
solve(arr);
}
public static void solve(int[] arr){
int[][] dp=new int[arr.length][arr.length];
int[][] sum=new int[arr.length][arr.length];
for(int j=0;j<arr.length;j++){
for(int i=j;i>=0;i--){
if(i==j){
sum[i][j]=arr[i];
dp[i][j]=0;
}else{
dp[i][j]=Integer.MAX_VALUE;
for(int k=i;k<j;k++){
sum[i][j]=sum[i][k]+sum[k+1][j];
dp[i][j]=Math.min(dp[i][k]+dp[k+1][j]+sum[i][j],dp[i][j]);
}
}
}
}
System.out.println(dp[0][arr.length-1]);
}
}