P1880 [NOI1995]石子合并(区间dp)

题目:https://www.luogu.org/problem/P1880

Description:

n堆石子摆成一圈,现在要合并成一堆,每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。计算出合并的最大分和最小分。

Solution: 

区间dp,分阶段划分问题。由于石子围成了环,现在把环转化为两倍长的链。变成 (2 * n - 1) 堆,其中第 i 堆与第(i + n)  堆相同,用动态规划求解后,取dp[1][n], dp[2][n+1] ,... ,dp[i][n+i -1] 中的最优值。

如果环是这样:1 2 3 4 

转化后的链:1 2 3 4 3 2 1 

转化后就可以往一个方向进行dp

 

区间 DP 的特点:

合并 :即将两个或多个部分进行整合,当然也可以反过来;

特征 :能将问题分解为能两两合并的形式;

求解 :对整个问题设最优值,枚举合并点,将问题分解为左右两个部分,最后合并两个部分的最优值得到原问题的最优值。

 

Code:

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int n;
int sum[300], a[300];
int dp1[300][300];//max
int dp2[300][300];//min
void init()
{
    memset(sum, 0, sizeof(sum));
    memset(dp1, 0, sizeof(dp1));
    memset(dp2, INF, sizeof(dp2));
    memset(a, 0, sizeof(a));
}
int main()
{
    init();
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        a[i + n] = a[i];
        dp2[i][i] = 0; //自己与自己合并得分为0
        dp2[i+n][i+n] = 0;
    }
    sum[1] = a[1];
    for(int i = 1; i <= 2 * n - 1; i++) sum[i] = sum[i - 1] + a[i];


    for(int len = 1; len <= n; len++) //划分区间长度,当区间的长度为len时
    {
        for(int i = 1; i <= 2 * n - 1; i++)//起点为i  //第n个值在最中间,就不用重复了,现在一共2*n-1个数
        {
            int j = i + len - 1;//终点为j
            for(int k = i; k < j && k <= 2 * n - 1 && j <= 2 * n - 1; k++)//分割点为k
            {
                dp1[i][j] = max(dp1[i][j], dp1[i][k] + dp1[k + 1][j] + sum[j] - sum[i - 1]);
                dp2[i][j] = min(dp2[i][j], dp2[i][k] + dp2[k + 1][j] + sum[j] - sum[i - 1]);
            }
        }
    }
    int Max = 0, Min = INF;
    for(int i = 1; i <= n; i++) //从不同的起点合并n堆的结果
    {
        Max = max(Max, dp1[i][i + n - 1]);
        Min = min(Min, dp2[i][i + n - 1]);
    }
    cout << Min << endl; 
    cout << Max << endl; 
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值