4456: 【入门】合并石子(2057)

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:3 解决:3

题目描述

在一个操场上一排地摆放着 lns="http://www.w3.org/1998/Math/MathML"> 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的 lns="http://www.w3.org/1998/Math/MathML">2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。

设计一个程序,计算出将 lns="http://www.w3.org/1998/Math/MathML"> 堆石子合并成一堆的最小得分。

输入

第一行为一个正整数 lns="http://www.w3.org/1998/Math/MathML"> (lns="http://www.w3.org/1998/Math/MathML">2100)。

以下 lns="http://www.w3.org/1998/Math/MathML"> 行,每行一个正整数,小于 lns="http://www.w3.org/1998/Math/MathML">10000,分别表示第 lns="http://www.w3.org/1998/Math/MathML"> 堆石子的个数(lns="http://www.w3.org/1998/Math/MathML">1)。

输出

为一个正整数,即最小得分。

样例输入 复制

7
13
7
8
16
21
4
18

样例输出 复制

239

提示

#include<bits/stdc++.h>
using namespace std;
/*
1.每次只能选相邻的2 堆石子合并成新的一堆
2.并将新的一堆石子数记为该次合并的得分
3.求将N堆石子合并成一堆的最小得分米
*/
const int N= 110;
int f[N][N]; //表示[l,r]合并区间内的数对应的最小得分
int s[N]; //表示前级和
int n;
int main(){
    cin>>n;
    //边界条件
    memset(f,0x3f,sizeof(f)); //默认初始化为无穷大
    for(int i= 1;i<= n;i++){
	    cin>>s[i];
	    s[i]+= s[i-1]; //求出前缀和
	    f[i][i]=0; //合并自己的默认得分为0
    }
    //穷举所有可能的长度
    for(int len=2;len<=n;len++){ //穷举区间可能的出发点
        for(int l=1;l+len-1<= n;l++){
		    int r=l+len-1; //区间的终点
			//穷举分割点 
			for(int k= l;k< r;k++){
			    f[l][r]= min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
		    }
		}
	}
	cout<<f[1][n];
	return 0;
}