当前位置: 首页 > news >正文

信息学奥赛一本通 1569:【 例 1】石子合并 | 洛谷 P1880 [NOI1995] 石子合并

【题目链接】

ybt 1569:【 例 1】石子合并
洛谷 P1880 [NOI1995] 石子合并

【题目考点】

1. 动态规划:区间动规
2. 环形序列问题

解决方法:破环为链
将长为n的环形序列变为长为 2 n − 1 2n-1 2n1的链式序列
原序列: a 1 , a 2 , . . . , a n − 1 , a n a_1, a_2, ..., a_{n-1}, a_n a1,a2,...,an1,an a n a_n an的下一个元素为 a 1 a_1 a1,形成环形序列。
破坏为链后,得到线性序列
a 1 , a 2 , . . . , a n − 1 , a n , a n + 1 , a n + 2 , . . . , a 2 n − 1 a_1, a_2, ..., a_{n-1}, a_n, a_{n+1}, a_{n+2}, ..., a_{2n-1} a1,a2,...,an1,an,an+1,an+2,...,a2n1
其中 a n + 1 = a 1 a_{n+1}=a_1 an+1=a1 a n + 2 = a 2 a_{n+2}=a_2 an+2=a2, …, a 2 n − 1 = a n − 1 a_{2n-1}=a_{n-1} a2n1=an1
环形序列中的任意区间,都能在线性序列中找到。

例:原序列中 a n − 1 , a n , a 1 , a 2 a_{n-1}, a_{n}, a_1, a_2 an1,an,a1,a2,在新的序列中就是 a n − 1 , a n , a n + 1 , a n + 2 a_{n-1}, a_{n}, a_{n+1}, a_{n+2} an1,an,an+1,an+2

【解题思路】

环形摆放n堆石子,合并时第n堆可以和第1堆合并。
面对环形序列问题,首先进行破坏为链,得到长为 2 n − 1 2n-1 2n1的线性序列a。
而后求出a序列的前缀和数组s。
在a序列上进行区间动规

1. 状态定义
  • 阶段:关注 a i ∼ a j a_i\sim a_j aiaj,即a序列区间 [ i , j ] [i, j] [i,j]
  • 决策:将哪两堆石子合并
  • 策略:合并石子的方案
  • 策略集合:a序列区间 [ i , j ] [i, j] [i,j]中元素的所有合并方案
  • 条件:分数最大或最小
  • 统计量:分数

状态定义:
d p M i n i , j dpMin_{i,j} dpMini,j:a序列区间 [ i , j ] [i, j] [i,j]中元素的所有合并方案中,分数最小的方案的分数。
d p M a x i , j dpMax_{i,j} dpMaxi,j:a序列区间 [ i , j ] [i, j] [i,j]中元素的所有合并方案中,分数最大的方案的分数。

由于所有a序列中的元素都是非负整数,那么合并的得分为非负整数。
d p M a x dpMax dpMax时,求最大值, d p M a x dpMax dpMax数组所有元素初值为 0 0 0即可。
d p M i n dpMin dpMin时,求最小值, d p M i n dpMin dpMin数组初值应该很大,先设为 I N F INF INF

一堆石子无法合并,合并的分数为0,那么设初值 d p M a x i , i = d p M i n i , i = 0 dpMax_{i,i}=dpMin_{i,i}=0 dpMaxi,i=dpMini,i=0

2. 状态转移方程

策略集合:a序列区间 [ i , j ] [i, j] [i,j]中元素的所有合并方案
最后一次的决策为最后一步如何合并。
a序列区间 [ i , j ] [i, j] [i,j]中元素进行合并,最后一步是两堆石子进行合并。接下来需要考虑这两堆石子分别由a序列中哪两个区间中的元素合并得到的。
设区间 [ i , j ] [i,j] [i,j]的分割点为 k k k。a序列区间 [ i , k ] [i, k] [i,k]中元素合并为第一堆石子,区间 [ k + 1 , j ] [k+1,j] [k+1,j]中元素合并为第2堆石子。第一个区间长度为1时 k k k最小,为 i i i。第二个区间长度为1时 k k k最大,为 j − 1 j-1 j1。所以 i ≤ k < j i\le k < j ik<j
已知a序列的前缀和为s,那么a序列区间 [ i , j ] [i, j] [i,j]中元素加和为 s j − s i − 1 s_j-s_{i-1} sjsi1
对于a序列区间 [ i , j ] [i, j] [i,j]中元素进行合并能得到的最大分数 d p M a x i , j dpMax_{i,j} dpMaxi,j,先将区间 [ i , k ] [i,k] [i,k]中元素合并,得到最大分数 d p M a x i , k dpMax_{i,k} dpMaxi,k。再将区间 [ k + 1 , j ] [k+1,j] [k+1,j]中元素合并,得到最大分数 d p M a x k + 1 , j dpMax_{k+1,j} dpMaxk+1,j,再将两堆石子合并,合并分数为a序列区间 [ i , j ] [i, j] [i,j]中元素加和 s j − s i − 1 s_j-s_{i-1} sjsi1,即 d p M a x i , j = d p M a x i , k + d p M a x k + 1 , j + s j − s i − 1 dpMax_{i,j}=dpMax_{i,k}+dpMax_{k+1,j}+s_j-s_{i-1} dpMaxi,j=dpMaxi,k+dpMaxk+1,j+sjsi1
对于所有可能的 k k k的取值,求 d p M a x i , j dpMax_{i,j} dpMaxi,j的最大值。
状态转移方程为:
d p M a x i , j = max ⁡ { d p M a x i , k + d p M a x k + 1 , j + s j − s i − 1 } , i ≤ k < j dpMax_{i,j}=\max\{dpMax_{i,k}+dpMax_{k+1,j}+s_j-s_{i-1}\}, i\le k < j dpMaxi,j=max{dpMaxi,k+dpMaxk+1,j+sjsi1},ik<j
同理:
d p M i n i , j = max ⁡ { d p M i n i , k + d p M i n k + 1 , j + s j − s i − 1 } , i ≤ k < j dpMin_{i,j}=\max\{dpMin_{i,k}+dpMin_{k+1,j}+s_j-s_{i-1}\}, i\le k < j dpMini,j=max{dpMini,k+dpMink+1,j+sjsi1},ik<j

3. 区间动规的具体实现

区间动规中,长度较小区间的状态是长度较长区间的状态的子状态。因此需要先求出长度较小的区间的状态,再求出长度较长的区间的状态。
外层循环的循环控制变量为区间长度 l e n len len l e n len len为1的情况已经求出,因此 l e n len len最小为2, l e n len len最大时只考虑长为 n n n的区间(因为环形序列上中最长的区间长度为n),因此 l e n len len从2循环到n。

内层循环控制变量为区间左端点 i i i,在整个长为 2 n − 1 2n-1 2n1的a序列上,所有以 i i i为起点长为 l e n len len的区间的状态都要求出,区间的右端点为 i + l e n − 1 i+len-1 i+len1,最后一个求出的区间的右端点为 2 n − 1 2n-1 2n1,因此 i i i最小时为1, i i i最大时满足 i + l e n − 1 = 2 n − 1 i+len-1=2n-1 i+len1=2n1,即 i + l e n − 1 < 2 n i+len-1<2n i+len1<2n

在循环控制变量为 i i i的循环内部,求出区间右端点 j = i + l e n − 1 j=i+len-1 j=i+len1。枚举分割点 k k k,执行状态转移方程。

求结果时,要把长为 n n n的环形序列合并为一堆石子,这个长为 n n n的环形序列在长为 2 n − 1 2n-1 2n1 a a a序列上对应的区间可以是 [ 1 , n ] [1,n] [1,n], [ 2 , n + 1 ] [2,n+1] [2,n+1], …, [ n − 1 , 2 n − 2 ] [n-1, 2n-2] [n1,2n2], [ n , 2 n − 1 ] [n, 2n-1] [n,2n1]。左端点为 i i i的长为n的区间,为 [ i , i + n − 1 ] [i, i+n-1] [i,i+n1] 1 ≤ i ≤ n 1\le i \le n 1in
以上所有长为 n n n的区间的 d p M a x dpMax dpMax的最大值,为将 n n n堆石子合并的最大得分。
以上所有长为 n n n的区间的 d p M i n dpMin dpMin的最小值,为将 n n n堆石子合并的最小得分。

【题解代码】

解法1:区间动规 破环为链
#include<bits/stdc++.h>
using namespace std;
#define N 205
#define INF 0x3f3f3f3f
int a[N], n, s[N];//s:a序列的前缀和 
int dpMin[N][N];//dpMin[i][j]:a[i]...a[j]进行合并的所有方案中,得分最少的方案的得分 
int dpMax[N][N];//dpMax[i][j]:a[i]...a[j]进行合并的所有方案中,得分最高的方案的得分 
int main()
{cin >> n;for(int i = 1; i <= n; ++i){cin >> a[i];a[i+n] = a[i];}for(int i = 1; i < 2*n; ++i)s[i] = s[i-1]+a[i];memset(dpMin, 0x3f, sizeof(dpMin));for(int i = 1; i < 2*n; ++i)dpMin[i][i] = 0;for(int len = 2; len <= n; ++len)for(int i = 1; i+len-1 < 2*n; ++i){int j = i+len-1;for(int k = i; k < j; ++k){dpMin[i][j] = min(dpMin[i][j], dpMin[i][k]+dpMin[k+1][j]+s[j]-s[i-1]);dpMax[i][j] = max(dpMax[i][j], dpMax[i][k]+dpMax[k+1][j]+s[j]-s[i-1]);}}int ansMax = 0, ansMin = INF;for(int i = 1; i <= n; ++i){ansMax = max(ansMax, dpMax[i][i+n-1]);ansMin = min(ansMin, dpMin[i][i+n-1]);}cout << ansMin << endl << ansMax;return 0; 
}
http://www.lqws.cn/news/130915.html

相关文章:

  • 【网络安全】漏洞分析:阿帕奇漏洞学习
  • Java观察者模式深度解析:构建松耦合事件驱动系统的艺术
  • OffSec 基础实践课程助力美国海岸警卫队学院网络团队革新训练
  • ArcGIS计算多个栅格数据的平均栅格
  • 行为型-模板模式
  • 将word文件转为kindle可识别的azw3文件的方法
  • 【Qt开发】文件
  • React---扩展补充
  • Flink进阶之路:解锁大数据处理新境界
  • React组件基础
  • 探索分布式存储与通信:去中心化共享及通訊(DSAC)
  • NER实践总结,记录一下自己实践遇到的各种问题。
  • 【python深度学习】Day 44 预训练模型
  • STM32学习之看门狗(理论篇)
  • OA工程自动化办公系统 – 免费Java源码
  • HTTP(超文本传输协议)详解
  • Linux命令:shell脚本文件名全局替换
  • 好坏质检二分类MLP 实战
  • 数字人技术的核心:AI与动作捕捉的双引擎驱动(210)
  • 网络安全中网络诈骗的攻防博弈
  • Flutter快速上手,入门教程
  • OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
  • 架构设计技巧——架构设计模板
  • 区块链技术发展现状与应用前景分析
  • Windows系统工具:WinToolsPlus 之 SQL Server Suspect/质疑/置疑/可疑/单用户等 修复
  • intense-rp-api开源程序是一个具有直观可视化界面的 API,可以将 DeepSeek 非正式地集成到 SillyTavern 中
  • C#学习第27天:时间和日期的处理
  • 【Linux】编译器gcc/g++及其库的详细介绍
  • 《高等数学》(同济大学·第7版)第一章第七节无穷小的比较
  • C++11 defaulted和deleted函数从入门到精通