蓝桥杯 合并石子

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

原来的思想:利用dp[i][j]表示从i到j堆石子合并的最小花费,这个需要i到j的所有连续子区间的结果迭代,取最小值,所以需要一个正向循环和一个反向循环,一个迭代正向的连续区间,一个迭代反向的连续区间。后来有点 乱,弄了两个二维数组,一个迭代最小花费,一个迭代石子数目。
代码如下:                                                                                                                                                                                                 
import java.math.BigInteger;
import java.util.Scanner;
public class 合并石子 {
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  Scanner cin=new Scanner(System.in);
  int n=cin.nextInt();
  int[] a=new int[n];
  for(int i=0;i<n;i++) {
   a[i]=cin.nextInt();
  }
  
  int[][] cost=new int[n][n];//花费
  int[][] num=new int[n][n];//石子数
  for(int i=0;i<n;i++) {
   for(int j=0;j<n;j++) {
    cost[i][j]=1000;
   }
  }
  for(int i=0;i<n;i++) {
   cost[i][i]=0;
   num[i][i]=a[i];
  }
  
  for(int i=1;i<n;i++) {
   for(int j=i-1;j>=0;j--) {
     cost[j][i]=Math.min(cost[j+1][i]+cost[j][j]+num[j+1][i]+a[j], cost[j][i]);
     num[j][i]=num[j+1][i]+a[j];
    
   }
   for(int k=i;k>0;k--) {
    cost[0][i]=Math.min(cost[k][i]+cost[0][k-1]+num[k][i]+num[0][k-1], cost[0][i]);
   }
  }
  
  
  System.out.println(cost[0][n-1]);
 }
}

然而仅仅是过了样例。。。。

后来看别人的解答,是按长度迭代的。。。先算出所有长度为2的区间的最小花费,再算3的,。。。一直扩展长度,因为是先算长度小的区间,所以后面的区间的子区间都是前面已经算好的了
代码还没有,忙完了再补上吧。。。。。。。。。。

发布了14 篇原创文章 · 获赞 2 · 访问量 5386

猜你喜欢

转载自blog.csdn.net/Wolf_South/article/details/79766009