[codevs 1048]石子合并

Codevs 1048 石子合并

 

题目描述 Description

有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。

 

输入描述 Input Description

第一行一个整数n(n<=100)

第二行n个整数w1,w2...wn  (wi <= 100)

 

输出描述 Output Description

一个整数表示最小合并代价

 

样例输入 Sample Input

4

4 1 1 4

 

样例输出 Sample Output

18

 

分析——区间dp

Dp啊经典题目吧

Dp[i][j]表示将i到j堆石子全部合并所花费的最小代价

Sum[i][j]表示 i到j堆石子数的和

测试数据

 

1

2

3

4

1

/

/

/

/

2

5

/

/

/

3

8

2

/

/

4

18

8

5

/

K为中间点枚举两边的石子堆,若石子堆还未被合并过加0

当前代价为最小之前的合并代价+此时i到j堆的石子数的和

即dp[i][j]=min(dp[i][j],dp[k][j]+a[j][i]+dp[i][k+1]);

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define maxn 2147483647
 8 
 9 using namespace std;
10 
11 int n,a[101][101],dp[101][101];
12 int main()
13 {
14     cin>>n;
15     for(int i=1;i<=n;i++)
16     {
17         scanf("%d",&a[i][i]);
18         dp[i][i]=0;
19         for(int j=1;j<i;j++)a[j][i]=a[j][i-1]+a[i][i];
20     }
21     for(int i=2;i<=n;i++)
22     {
23         for(int j=i-1;j>=1;j--)
24         {
25             dp[i][j]=maxn;
26             if(j==i-1)dp[i][j]=a[j][i];
27             for(int k=j;k<i;k++)
28                 dp[i][j]=min(dp[i][j],dp[k][j]+a[j][i]+dp[i][k+1]);
29         }
30     }
31     cout<<dp[n][1];
32     system("pause");
33     return 0;
34 }
View Code

 

posted @ 2017-07-06 13:48  hdsmwww  阅读(135)  评论(0编辑  收藏  举报