美团笔试题

1. 合并金币问题

  动态规划,dp[j][i] 表示合并第j个到第i个金币的总花费(j>=i  从前往后的顺序合并)

  j==i 时候     dp=0    就一个金币,无需合并 ;

  i==j+1 时候  dp=相邻两个金币和    相邻;

  其他情况      dp[j][i] = min{ dp[j][k] + dp[k+1][i] + sum }   j<=k<i ,分别合并此区间内左区间dp[j][k],右区间 dp[k+1][i] ,最后合并左右区间还需花费 金币j到i的和 sum

  

import java.util.Scanner;

/**
 * @author zzm
 * @data 2020/4/17 21:18
 * 有 N 堆金币排成一排,第 i 堆中有 C[i] 块金币。每次合并都会将相邻的两堆金币合并为一堆,成本为这两堆金币块数之和。
 * 经过N-1次合并,最终将所有金币合并为一堆。请找出将金币合并为一堆的最低成本。
 * 其中,1 <= N <= 30,1 <= C[i] <= 100
 * 输入描述:
 * 第一行输入一个数字 N 表示有 N 堆金币
 * 第二行输入 N 个数字表示每堆金币的数量 C[i]
 * 输出描述:
 * 输出一个数字 S 表示最小的合并成一堆的成本
 */
public class MTmergeCoin {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int len = Integer.parseInt(scanner.nextLine());
        String s = scanner.nextLine();
        String[] split = s.split(" ");
        int[] coins = new int[len];
        int[] sum = new int[len + 1];
        for (int i = 0; i < len; i++) {
            coins[i] = Integer.parseInt(split[i]);
            sum[i + 1] = coins[i] + sum[i];
        }

        int[][] dp = new int[len + 1][len + 1];

        for (int i = 1; i <= len; i++) {
            for (int j = i; j > 0; j--) {
                if (i == j) dp[i][j] = 0;
                else if (j == i - 1) dp[j][i] = coins[i - 1] + coins[i - 2];
                else {
                    dp[j][i] = Integer.MAX_VALUE;
                    for (int k = j; k < i; k++) {
                        dp[j][i] = Math.min(dp[j][i], dp[j][k] + dp[k + 1][i] + sum[i] - sum[j - 1]);
                    }
                }
            }
        }
        System.out.println(dp[1][len]);
    }
}

  

猜你喜欢

转载自www.cnblogs.com/zzm96/p/12724376.html