NYOJ 737 石子合并(一)

分析:

本题为区间型动态规划,dp[i][j] 表示从第 i 堆合并到第 j 堆的最小代价,

sum[i][i] 表示第 i 堆到第 j 堆的石子总和,则动态转移方程:

dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[i][j])  (i <= k <= j - 1)。

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 200 + 5;
 6 const int INF = 1000000000;
 7 int dp[maxn][maxn], sum[maxn][maxn], stone[maxn];
 8 int main()
 9 {
10     int n;
11     int i, j, k;
12     while(~scanf("%d", &n))
13     {
14         for(i = 1; i <= n; i ++)
15             scanf("%d", &stone[i]);
16         for(i = 1; i <= n; i ++)
17         {
18             dp[i][i] = 0;    //不合并,代价为0
19             sum[i][i] = stone[i];
20             for(j = i + 1; j <= n; j ++)
21                 sum[i][j] = sum[i][j - 1] + stone[j];
22         }
23         for(int dui = 2; dui <= n; dui ++)  //合并石子的堆数
24         {
25             for(i = 1; i <= n - dui + 1; i ++)  //从第 i 堆到第 j 堆
26             {
27                 j = dui + i - 1;
28                 dp[i][j] = INF;
29                 for(k = i; k <= j - 1; k ++)
30                     dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[i][j]);
31             }
32         }
33         printf("%d
", dp[1][n]);
34     }
35     return 0;
36 }
View Code
原文地址:https://www.cnblogs.com/Houheshuai/p/3867524.html