动态规划:洛谷P1880[NOI1995] 石子合并 区间DP 前缀和

P1880[NOI1995] 石子合并

 

     相较于P1775 石子合并(弱化版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn),洛谷P1775,这题就是变成了环形石子,我们可以用把环形拉成链,n->2n,这样从1->n的每一个为元素起点,长度为n,得到的序列,就是环形的每一个元素为起点的每一种可能,然后像P1775一样的方法区间DP,具体可以看我的题解,讲的非常清楚:动态规划:P1775石子合并(弱化版)区间DP、前缀和 - 朱朱成 - 博客园 (cnblogs.com),最后有所区别的是ans并非dp[1][n],而要用一个for循环遍历dp[i][i+n]的最优解,注意这里求最大值和最小值,需要建立两个DP数组,区别就是max和min,还有初始值求max要初始化为0,求Min初始化为INT_MAX。

    上代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<string>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn = 210;
 8 int dp1[maxn][maxn];
 9 int dp2[maxn][maxn];
10 int a[maxn];
11 int pre[maxn];
12 const int inf = 0x7fffffff;
13 int main()
14 {
15     int n;
16     cin >> n;
17     for (int i = 1; i <= n; ++i)
18     {
19         cin >> a[i];
20         a[i + n] = a[i];
21     }
22     for (int i = 1; i <= 2 * n; ++i)
23     {
24         pre[i] = pre[i - 1] + a[i];
25     }
26     for (int len = 2; len <= n; ++len)
27     {
28         for (int l = 1; l + len - 1 <= 2*n; ++l)
29         {
30             int r = l + len - 1;
31             dp2[l][r] = inf;//算最小值的时候给一个大值 便于计算最小值
32             for (int k = l; k < r; ++k)
33             {
34                 dp1[l][r] = max(dp1[l][r], dp1[l][k] + dp1[k + 1][r] + pre[r] - pre[l - 1]);
35                 dp2[l][r] = min(dp2[l][r], dp2[l][k] + dp2[k + 1][r] + pre[r] - pre[l - 1]);
36             }
37         }
38 
39     }
40     int ans1 = inf, ans2 = -inf;
41     for (int i = 1; i <= n; ++i)
42     {
43         ans1 = min(dp2[i][n + i - 1], ans1);
44         ans2 = max(dp1[i][n + i - 1], ans2);
45     }
46     cout << ans1 << endl << ans2;
47     return 0;
48 
49 }

 

 

posted @ 2022-04-17 16:34  朱朱成  阅读(55)  评论(0编辑  收藏  举报