CSU - 1592 石子归并

现在有n堆石子,第i堆有ai个石子。现在要把这些石子合并成一堆,每次只能合并相邻两个,每次合并的代价是两堆石子的总石子数。求合并所有石子的最小代价。

 

Input

第一行包含一个整数T(T<=50),表示数据组数。
每组数据第一行包含一个整数n(2<=n<=100),表示石子的堆数。
第二行包含n个正整数ai(ai<=100),表示每堆石子的石子数。

 

Output

每组数据仅一行,表示最小合并代价。

 

Sample Input

2
4
1 2 3 4
5
3 5 2 1 4

Sample Output

19
33

Hint

 

用区间DP的lik通式做。

转移方程:dp【i】【j】=min(dp【i】【j】,dp【i】【k】+dp【k+1】【j】+c)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 
 6 using namespace std;
 7 
 8 int a[105],b[105][105],c[105];
 9 
10 int dfs(int i,int j)
11 {
12     if(b[i][j]!=-1)
13         return b[i][j];
14     int t=1e9;
15     for(int k=i;k<j;k++)
16     {
17         t=min(t,dfs(i,k)+dfs(k+1,j)+c[j]-c[i-1]);
18         //cout<<i<< " "<<j<<" "<<t<<endl;
19     }
20 //    b[i][j]=t;
21     return b[i][j]=t;
22 }
23 
24 int main()
25 {
26     int T;
27     scanf("%d",&T);
28     while(T--)
29     {
30         int n;
31         scanf("%d",&n);
32         for(int i=0;i<n;i++)
33             for(int j=0;j<n;j++)
34                 b[i][j]=-1;
35         for(int i=0;i<n;i++)
36         {
37             scanf("%d",&a[i]);
38             c[i]=a[i]+c[i-1];
39             //cout<<c[i]<<endl;
40             b[i][i]=0;
41         }
42         int s=dfs(0,n-1);
43         printf("%d\n",s);
44     }    
45     
46     
47     
48     return 0;
49 } 

 

posted @ 2017-08-05 08:32  西北会法语  阅读(195)  评论(0编辑  收藏  举报