NOI1995 石子合并 [Luogu P1880]
2024-09-01 16:20:06
一道区间dp的模板题,这里主要记一下dp时环形数据的处理。
简略版:方法一:枚举分开的位置,将圈化为链,因此要做n次。
方法二:将链重复两次,即做一个2n-1长度的链,其中第i(i<=n)堆石子与i+n堆相同。
对整个长链dp后,枚举(1, n), (2, n+1) ... (n, 2n-1),取最值即可。
题目描述
在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
输入格式
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出格式
输出共2行,第1行为最小得分,第2行为最大得分.
输入输出样例
输入 #14
4 5 9 4输出 #143
54
由于只有相邻的石子才能被合成为一堆,因此在所有时刻的任意一堆石子(无论被合成了几次)都可以看做相邻几堆石子的和。即,均可以用一个闭区间[l, r]表示。
进行动态规划时,两堆石子的合并可以被看作两个区间的合并,即两个小区间的信息向一个大区间转移。
为处理环形数据,这里采用的方法是将数组arr重复两次,即arr[i+n] = arr[i](i<=n)。
设sum[i]为数组arr(重复后)的前缀和,dp1[i][j]、dp2[i][j]分别为第i堆至第j堆石子合并的得分最小值、最大值。
状态转移方程:
dp1[i][j] = min{dp1[i][k] + dp1[k+][j] + sum[j] - sum[i-]}
dp2[i][j] = max{dp2[i][k] + dp2[k+][j] + sum[j] - sum[i-]}
(i <= k <= j-)
注意初始化dp1[i][i] = INF,dp2[i][i] = 0。
代码实现后时间复杂度为O(8n3),相对与朴素的拆环方式(枚举断点做n次dp)的时间复杂度O(n4)在数据较大时有优势。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MAXN 300
using namespace std;
int dp1[MAXN][MAXN], dp2[MAXN][MAXN];
int arr[MAXN], sum[MAXN];
int n, ans_min = INF, ans_max = -;
void in_put(){
scanf("%d", &n);
for(int i=; i<=n; i++){
scanf("%d", &arr[i]);
arr[i+n] = arr[i];
}
}
void dp(){
for(int len=; len<=n; len++){
for(int i=; i<=*n; i++){
int end = i + len - ;
dp1[i][end] = INF, dp2[i][end] = -;
for(int j=i; j<end; j++){
dp1[i][end] = min(dp1[i][end], dp1[i][j] + dp1[j+][end]);
dp2[i][end] = max(dp2[i][end], dp2[i][j] + dp2[j+][end]);
}
dp1[i][end] += sum[end] - sum[i-];
dp2[i][end] += sum[end] - sum[i-];
}
}
for(int i=; i<=n; i++){
if(dp1[i][i+n-] < ans_min) ans_min = dp1[i][i+n-];
if(dp2[i][i+n-] > ans_max) ans_max = dp2[i][i+n-];
}
}
int main(){
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
in_put();
for(int i=; i<=n*; i++){
sum[i] = sum[i-] + arr[i];
dp1[i][i] = , dp2[i][i] = ;
}
dp();
printf("%d\n%d", ans_min, ans_max);
return ;
}
最新文章
- AngularJS 第四天----控制器
- WPF 自定义标题栏 自定义菜单栏
- Composer Player 属性设置
- WebView相关
- Java 生成16/32位 MD5
- zabbix自动发现监控url
- [转载]Macaca 测试 Android 应用:UIAutomator
- RGBA 与opacity
- SSIS hang with unhandle exception
- C# 常见集合之前的转换
- C语言volatile关键字
- 不相交集python实现
- 十六进制string转换UIColor -备用
- linux之SQL语句简明教程
- gulp + es6 + babel+ angular 搭建环境并实现简单的路由
- Oracle使用笔记(三)
- 微服务监控zipkin+asp.net core
- 分页-jquery.page.js插件在使用时重复触发“上一页”和“下一页”操作
- python ftp文件夹文件递归上传推送
- 阿里云Linux系统基线检查优化
热门文章
- VR中的“寻路(wayfinding)”
- 虚拟现实研究经典问卷Presence Questionnaire (PQ) 详细介绍
- IDEA 学习笔记之 1.5已经过时问题
- UVA - 11400 Lighting System Design
- Mac 10.14在新窗口中打开文件夹
- 引入flask_cache时出现ModuleNotFoundError: No module named &#39;flask.ext&#39;
- How to Get What You Want 如何得到你想要的
- Vue的介绍及安装和导入
- Jenkins构建Jmeter项目之源代码管理(SVN)
- 如何在项目中使用Spring异步调用注解@Async