• 洛谷 P1080 石子合并 ( 区间DP )


    题意 : 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分。

    分析 : 

    有大佬给出了四边形不等式优化........

    发现并不会,于是开始学习区间DP的写法

    对于某一个特定的区间 (i, j) 其合并成一个石子是从

    某两个属于这个区间且连续不相交区间合并而来

    即假设有断点 k 则 (i, j) = (i, k) + (k+1, j) + Sum(i, j)

    这里定义 Sum(i, j) 为 i 到 j 这个区间石子的总和、前缀和可实现

    只要枚举断点就可以知道 (i, j) 的最优值是多少了

    定义 dp[i][j] = 区间 i 到 j 的石子合并代价的最值

    转移方程就是枚举断点 dp[i][j] = dp[i][k] + dp[k+1][j] + Sum(i, j)

    但是这个有一个坑,如果你用三重循环,分别表示

    区间开头 i、区间结尾 j、区间断点 k 来进行 状态转移

    这样是错误的,因为 dp[k+1][j] 在这样的循环下是还未确定的

    所以有个技巧就是将一重循环变成区间长度,即

    区间长度 len、区间开头 i、区间断点 k

    还有一个问题就是,题目给出来的石头是链装的

    只要“断环为链”即复制一份黏到末尾就行了

    #include<bits/stdc++.h>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int maxn = 2e2 + 10;
    int dp1[maxn][maxn], dp2[maxn][maxn];
    int PreSum[maxn];
    int arr[maxn];
    int N;
    
    int main(void)
    {
        scanf("%d", &N);
    
        memset(dp1, 0, sizeof(dp1));
        memset(dp2, 0, sizeof(dp2));
        memset(PreSum, 0, sizeof(PreSum));
    
        for(int i=1; i<=N; i++){
            scanf("%d", &arr[i]);
            arr[i+N] = arr[i];
        }
    
        for(int i=1; i<=(N<<1); i++)
            PreSum[i] = PreSum[i-1] + arr[i];
    
        for(int len=2; len<=N; len++){
            for(int i=1; i<=(N<<1)-len+1; i++){
                int j = i + len - 1;
                int MX = 0, MM = INF;
                for(int k=i; k<j; k++){
                    MM = min(MM, dp1[i][k]+dp1[k+1][j]+PreSum[j]-PreSum[i-1]);
                    MX = max(MX, dp2[i][k]+dp2[k+1][j]+PreSum[j]-PreSum[i-1]);
                }
                dp1[i][j] = MM;
                dp2[i][j] = MX;
            }
        }
    
        int MX = 0, MM = INF;
        for(int i=1; i<=N; i++){
            MM = min(MM, dp1[i][i+N-1]);
            MX = max(MX, dp2[i][i+N-1]);
        }
    
        printf("%d
    %d
    ", MM, MX);
        return 0;
    }
    View Code
  • 相关阅读:
    linux brige中mac地址的比较
    BCM6358 加上TTL线 OPENWRT刷机全方位教程
    BCM6358 进入CFE界面
    BCM6358编译openwrt并刷机
    BCM6358开发板硬件资源 【OPENWRT刷机全方位教程】
    WRT54GS openwrt pppoe拨号
    CentOS6.5安装JDK1.8
    Sql Server 事物
    linux系统中的删除操作
    Java学习-集合的理解
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/8906817.html
Copyright © 2020-2023  润新知