DP(4)--区间DP

news2024/9/20 6:34:51

将n(1≤n≤200)堆石子绕圆形操场摆放,现要将石子有次序地合并成一堆。
规定每次只能选相邻的两堆石子合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 
(1)选择一种合并石子的方案,使得做n-1次合并,得分的总和最小。 
(2)选择一种合并石子的方案,使得做n-1次合并,得分的总和最大
输入
4
4 5 9 4
输出
43
54

线性结构是N个数据元素以有序的方式排列。访问线性结构一般采用由前至后的遍历方法。
线性动态规划就是在线性数据的基础上,通过某种递推方式(状态转移方程)得到最终结构的一种规划算法。
sum[i]: 从第1堆到第i堆石子数总和
fmax[i][j]: 从第i堆石子合并到第j堆石子的最大得分
fmin[i][j]: 从第i堆石子合并到第j堆石子的最小得分

初始化: fmax[i][i] = 0, fmin[i][i]= INF
状态方程:
fmax[i][j] = max{fmax[i][k]+fmax[k+1][j]+sum[j]-sum[i-1]} i <= k < j
fmin[i][j] = min{fmin[i][k]+fmin[k+1][j]+sum[j]-sum[i-1]} i <= k < j

由于题中围成一个环,我们将这条链再延长一倍,变成2*n堆,地中第i堆与第n+i堆相同,
动态规划求解后,答案为f(1,n), f(2,n+1), ... , f(n-1,2*n-2)中的最优解

状态转移
要计算f(i,j)的值时需知道所有f(i,k)和f(k+1,j)的值,
以len=j-i+1作为DP 的区间长度,从小到大枚举len,
然后枚举i的值,根据len和i用公式计算出j的值,然后枚举k,时间复杂度为O(n^3)

/*  https://loj.ac/problem/10147  */
#include <iostream>
using namespace std;

const int MAXN = 201;
const int INF = 0x3f3f3f3f;
int arr[2*MAXN];
int sum[2*MAXN];
int fmax[2*MAXN][2*MAXN];
int fmin[2*MAXN][2*MAXN];

int main()
{
    int i, j, k, n, len;
    cin >> n;
    for (i = 1; i <= n; ++i)
    {
        cin >> arr[i];
        arr[n+i] = arr[i]; 
    }
    for (i = 1; i <=(n<<1); ++i)
        sum[i] = sum[i-1] + arr[i];

    for (len = 2; len <= n; ++len)
        for (i = 1; i <= (n<<1)-len+1; ++i)
        {
            j = i + len - 1;
            // 初始化
            fmax[i][j] = 0;
            fmin[i][j] = INF;
            for (k = i; k < j; ++k)
            {
                fmax[i][j] = max(fmax[i][j], fmax[i][k] + fmax[k+1][j] + sum[j] - sum[i-1]);
                fmin[i][j] = min(fmin[i][j], fmin[i][k] + fmin[k+1][j] + sum[j] - sum[i-1]);
            }
        }

    int ansmax = 0, ansmin = INF;
    for (i = 1; i < n; ++i)
    {
        ansmax = max(ansmax, fmax[i][i+n-1]);
        ansmin = min(ansmin, fmin[i][i+n-1]);
    }

    cout << ansmin << endl << ansmax << endl;


    return 0;
}


四边形不等式优化请参考

https://oi-wiki.org/dp/opt/quadrangle/

https://www.cnblogs.com/a1b3c7d9/p/10984353.html

dp[i][j]=min{dp[i][k]+dp[k+1][j]+w[i][j]} (i≤k<j)
把dp[i][k]+dp[k+1][j]取得最值的那个k, 称为dp[i][j]的最优决策点。

 

 

#include <iostream>
using namespace std;
const int MAXN = 201;
const int INF = 0x3f3f3f3f;
int arr[2*MAXN];
int sum[2*MAXN];
int fmax[2*MAXN][2*MAXN];
int fmin[2*MAXN][2*MAXN];
int ma[2*MAXN][2*MAXN]; //ma[i][j]: 从第i堆石子合并到第j堆石子的最大得分时的最优决策点
int mi[2*MAXN][2*MAXN]; //mi[i][j]: 从第i堆石子合并到第j堆石子的最小得分时的最优决策点

int main()
{
    int i, j, k, n, len, t;
    cin >> n;
    for (i = 1; i <= n; ++i)
    {
        cin >> arr[i];
        arr[n+i] = arr[i];
    }
    for (i = 1; i <=(n<<1); ++i)
    {
        sum[i] = sum[i-1] + arr[i];
        ma[i][i] = i;
        mi[i][i] = i;
    }

    for (len = 2; len <= n; ++len)
        for (i = 1; i <= (n<<1)-len+1; ++i)
        {
            j = i + len - 1;
            // 初始化
            fmax[i][j] = 0;
            fmin[i][j] = INF;
            // 四边形不等式优化
            for (k = ma[i][j-1]; k <= ma[i+1][j] && k < j; ++k)
            {
                t = fmax[i][k] + fmax[k+1][j] + sum[j] - sum[i-1];
                if (fmax[i][j] < t)
                {
                    fmax[i][j] = t;
                    ma[i][j] = k;
                }
            }

            for (k = mi[i][j-1]; k <= mi[i+1][j] && k < j; ++k)
            {
                t = fmin[i][k] + fmin[k+1][j] + sum[j] - sum[i-1];
                if (fmin[i][j] > t)
                {
                    fmin[i][j] = t;
                    mi[i][j] = k;
                }
            }
        }

    int ansmax = 0, ansmin = INF;
    for (i = 1; i < n; ++i)
    {
        ansmax = max(ansmax, fmax[i][i+n-1]);
        ansmin = min(ansmin, fmin[i][i+n-1]);
    }

    cout << ansmin << endl << ansmax << endl;


    return 0;
}
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/378234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

比特数据结构与算法(第四章_下)二叉树的遍历

本章将会详细讲解二叉树遍历的四种方式&#xff0c;分别为前序遍历、中序遍历、后续遍历和层序遍历。在学习遍历之前&#xff0c;会先带大家回顾一下二叉树的基本概念。学习二叉树的基本操作前&#xff0c;需要先创建一颗二叉树&#xff0c;然后才能学习其相关的基本操作&#…

中国一直是亚马逊云科技在全球业务布局中最重要的国家之一

在走进经济筑底重启回升的2023年&#xff0c;我们该如何直面这场需要时间验证的修复之旅&#xff1f;亚马逊全球副总裁、亚马逊云科技大中华区执行董事张文翊与《经济观察报》App的“企业家说2023”栏目展开对谈&#xff0c;分享亚马逊云科技如何立于云端&#xff0c;帮助企业上…

Android ART dex2oat

一、什么是dex2oat Dex2oat (dalvik excutable file to optimized art file) &#xff0c;是一个对 dex 文件进行编译优化的程序&#xff0c;在我们的 Android 手机中的位置是 /system/bin/dex2oat&#xff0c;对应的源码路径为 android/art/dex2oat/dex2oat.cc&#xff0c;通…

谷歌搜索技巧大全 | 谷歌高级搜索语法指令

谷歌搜索技巧是利用各种高级搜索语法或者搜索指令&#xff0c;让我们能够使用Google进行精确化的搜索&#xff0c;外贸找客户和学术文件查找都可以应用到这些搜索技巧。(大部分命令也适用百度搜索)。Google通过互联网收集数据&#xff0c;抓取有意义的信息&#xff0c;将其存储…

flask入门-4.项目实战

4. 项目实战1 1. 问答平台项目结构搭建 项目结构 config.py hostname "127.0.0.1" port 3306 username "root" password "root"database "flask_qa"# 在 app.config 中设置连接数据库的信息 SQLALCHEMY_DATABASE_URI f"…

【Redis】什么是缓存与数据库双写不一致?怎么解决?

1. 热点缓存重建 我们以热点缓存 key 重建来一步步引出什么是缓存与数据库双写不一致&#xff0c;及其解决办法。 1.1 什么是热点缓存重建 在实际开发中&#xff0c;开发人员使用 “缓存 过期时间” 的策略来实现加速数据读写和内存使用率&#xff0c;这种策略能满足大多数…

ECharts基础知识详细介绍

文章目录知识点ECharts 实例ECharts 基础配置组件seriesdataset用 option 描述图表titletooltiplegend 图例组件toolbox 工具栏坐标轴知识点 ECharts 实例series 与 datasetECharts 基础配置用 option 描述图表坐标系 ECharts 实例 一个网页中可以创建多个 ECharts 实例。每个…

JPA——Java.util.Date和Java.sql.Date

纵观整个项目的字段&#xff0c;最难搞的就是Date类型。今天我们就好好唠唠java中的两个Date类 一、Java.sql.Date 1. 构造方法 Date date new Date(System.currentTimeMillis());System.out.println(date);//2023-02-282. 常用方法&#xff1a; 方法作用void setTime(long…

【Java开发】JUC基础 04:Synchronized、死锁、Lock锁

1 概念介绍并发&#xff1a;同一个对象被多个线程同时操作&#x1f4cc; 线程同步现实生活中&#xff0c;我们会遇到“同一个资源&#xff0c;多个人都想使用”的问题&#xff0c;比如&#xff0c;食堂排队打饭,每个人都想吃饭&#xff0c;最天然的解决办法就是&#xff0c;排队…

强化学习RL 04: Actor-Critic Algorithm

actor: 是policy network&#xff0c;通过生成动作概率分布&#xff0c;用来控制agent运动&#xff0c;类似“运动员”。critic: 是value network&#xff0c;用来给动作进行打分&#xff0c;类似“裁判”。构造这两个网络&#xff0c;并通过environment奖励来学习这两个网络。…

AQS抽象队列同步器

aqs 抽象队列同步器&#xff0c;内部存储了一个valitail修饰的status 和内部类node &#xff0c;来实现对共享变量并发同步队列机制,以reentrantLock为例&#xff0c;lock底层实际上调用的是sync的lock&#xff0c;会调用cas对status的状态进行修改&#xff0c;来确定是否获得锁…

学习 Python 之 Pygame 开发魂斗罗(七)

学习 Python 之 Pygame 开发魂斗罗&#xff08;七&#xff09;继续编写魂斗罗1. 载入水中图片并添加在水中的标志2. 修改玩家类函数3. 增加河的碰撞体4. 实现玩家在河中的样子继续编写魂斗罗 在上次的博客学习 Python 之 Pygame 开发魂斗罗&#xff08;六&#xff09;中&#…

csgo搬砖项目详细拆解,附选品+详细操作教程

项目实操 一&#xff1a;项目原理 csgo这款游戏不知道大家玩过没有&#xff0c;如果不了解的话&#xff0c;那你肯定知道穿越火线这款游戏吧&#xff0c;都是一个类型的射击游戏。 说到csgo&#xff0c;就得所以一下今天项目的平台steam&#xff0c;它是一个游戏平台&#x…

Redis面试问题总结

1. 什么是Redis&#xff1f;Redis 是一个使用 C 语言写成的&#xff0c;开源的高性能key-value非关系缓存数据库。它支持存储的value类型相对更多&#xff0c;包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash&#xff08;哈希类型&#xff09;。…

【Redis】Redis主从同步中数据同步原理

【Redis】Redis主从同步中数据同步原理 文章目录【Redis】Redis主从同步中数据同步原理1. 全量同步1.1 判断是否第一次数据同步2. 增量同步3. 优化Redis主从集群4. 总结1. 全量同步 主从第一次同步是全量同步。 数据同步包括以下三个阶段&#xff1a; 在从节点执行slaveof命令…

技术分担产品之忧(上):挑选有业务专家潜力的人

你好&#xff0c;我是王植萌&#xff0c;去哪儿网的高级技术总监、TC主席。从2014年起&#xff0c;担任一个部门的技术负责人&#xff0c;有8年技术总监经验、5年TC主席的经验。这节课我会从去哪儿网产研融合的经验出发&#xff0c;和你聊一聊怎么让技术分担产品之忧。 技术分…

SSL证书与我们普通人之间有什么关系

对于很多普通人来说&#xff0c;SSL证书似乎会感到很陌生&#xff0c;总觉得离自己很遥远&#xff0c;从而并没有引起察觉。要是这么想的话那么就真的大错特错了&#xff0c;其实SSL证书与我们普通人之间还是很密密相关的&#xff0c;是我们应该都需要关注的&#xff0c;下面就…

cesium学习记录02-vue项目中cesium的配置与使用

1&#xff0c;下载cesium包 &#xff08;当然&#xff0c;使用npm install cesium安装也是可以的&#xff0c;不过在这里选择下载包放到本地&#xff09; 官方下载地址 笔者的cesium版本为1.101 2&#xff0c;将下载的Cesium文件夹放到项目里某个位置 这里&#xff0c;笔者将…

又一个国内类ChatGPT模型?【秘塔科技上线自研LLM大模型「对话写作猫」】

又一个国内类ChatGPT模型&#xff1f;【秘塔科技上线自研LLM大模型「对话写作猫」】 &#xff08;马上被打脸 ~ ~&#xff09; 一直期待中国有没有类ChatGPT产品可以出现。 昨天&#xff0c;2023年2月27日&#xff0c;秘塔科技上线了自研LLM大模型「对话写作猫」&#xff0c;…

全屋Wi-Fi领域「兵戎相见」,鸿雁这一局赢面大不大?

作者 | 牧之 编辑 | 小沐 出品 | 智哪儿 zhinaer.cn相比全屋智能&#xff0c;另一个刚需属性更强&#xff0c;消费规模更大的细分市场&#xff0c;便是全屋Wi-Fi。在这个板块&#xff0c;当鸿雁入局的时候&#xff0c;笔者还是有些许的「诧异」。毕竟&#xff0c;鸿雁给大众的印…