合并石子java

来源:互联网 发布:国语电影排行榜 知乎 编辑:程序博客网 时间:2024/06/11 08:27

算法提高 合并石子  

时间限制:2.0s   内存限制:256.0MB
   


锦囊1
锦囊2
锦囊3
问题描述
  在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数。求把所有石子合并成一堆的最小花费。
输入格式
  输入第一行包含一个整数n,表示石子的堆数。
  接下来一行,包含n个整数,按顺序给出每堆石子的大小 。
输出格式
  输出一个整数,表示合并的最小花费。
样例输入
5
1 2 3 4 5
样例输出
33
数据规模和约定
  1<=n<=1000, 每堆石子至少1颗,最多10000颗。


题解思路:

1.这是一道动态规划题目

2.用dp[i][j]表示:合并  第i堆石子  到   第j堆石子  的最小花费;

3.对于单独的一堆石子i,dp[i][i] = 0;

4.对于 第 i 堆  到  第 j 堆  石子(i != j),dp[i][j]初始设为无穷大;

5.设 k 把i->j石子分成两堆,[i][i+k]表示前一堆,[i+k+1][j]表示后一堆;

6.j-i+1表示宽度d,可以从2到n;

7.k 可以从0取到d-1;

9.sum[i]表示前i堆的和,sum[j]-sum[i-1]表示第[i]堆到第[j]堆的和;

8.由此得到状态转移方程dp[i][j] = min(dp[i][j],dp[i][i+k]+dp[i+k+1][j]   +   sum[j]-sum[i-1]);


以下是java 代码:

package 动态规划;import java.util.Scanner;public class 合并石子 {public static void main(String[] args) {Hbsz hbsz = new Hbsz();}}class Hbsz{int n;int[] shizi;//各堆石子int[] sum;//前i堆石子的和int[][] dp;//合并i到j堆石子的最小花费public Hbsz(){Scanner sca = new Scanner(System.in);n = sca.nextInt();shizi = new int[n+1];sum = new int[n+1];//sum[i]表示前i堆的和dp = new int[n+1][n+1];for(int i=1;i<=n;i++){shizi[i] = sca.nextInt();sum[i] = sum[i-1]+shizi[i];dp[i][i] = 0;//合并1堆的费用为0}for(int i=2;i<=n;i++){//宽度for(int j=1;j<=n-i+1;j++){//起始点int right =j+i-1;//右边的点dp[j][right] = Integer.MAX_VALUE;//默认设置为INFfor(int k=0;k+1<i;k++){//分割点dp[j][right] = Math.min(dp[j][right],dp[j][j+k]+dp[j+k+1][right]); }dp[j][right]+=sum[right] - sum[j-1];//避免重复计算,只在最后得到最小值加上即可//System.out.println("dp"+j+" "+right+":"+dp[j][right]);}}System.out.println(dp[1][n]);}}


0 0
原创粉丝点击