首先来个题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=737

有个更难的版本(不过很好玩):http://www.lydsy.com/JudgeOnline/problem.php?id=3229

题目:

石子合并(一)

时间限制:65535 KB
难度:3
 
描述
    有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
 
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
3
1 2 3
7
13 7 8 16 21 4 18
样例输出
9
239


最普通的算法O(n^3):

 1 #include <fstream>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <cmath>
 7 using namespace std;
 8 
 9 const int N=205;
10 const int INF=0x7fffffff;
11 int n;
12 int a[N],sum[N],dp[N][N];
13 
14 void f();
15 
16 int main(){
17     //freopen("D:\\input.in","r",stdin);
18     while(~scanf("%d",&n)){
19         sum[0]=0;
20         for(int i=1;i<=n;i++){
21             scanf("%d",&a[i]);
22             sum[i]=sum[i-1]+a[i];
23         }
24         f();
25         printf("%d\n",dp[1][n]);
26     }
27     return 0;
28 }
29 void f(){
30     for(int i=1;i<=n;i++) dp[i][i]=0;
31     for(int r=1;r<n;r++){
32         for(int i=1;i<n;i++){
33             int j=i+r;
34             if(j>n) break;
35             dp[i][j]=INF;
36             for(int k=i;k<=j;k++){
37                 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
38             }
39             dp[i][j]+=sum[j]-sum[i-1];
40         }
41     }
42 }        
224ms

相关文章: