一道区间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行为最大得分.

输入输出样例

输入 #1

4
4 5 9 4
输出 #1

43
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 ;
}

最新文章

  1. AngularJS 第四天----控制器
  2. WPF 自定义标题栏 自定义菜单栏
  3. Composer Player 属性设置
  4. WebView相关
  5. Java 生成16/32位 MD5
  6. zabbix自动发现监控url
  7. [转载]Macaca 测试 Android 应用:UIAutomator
  8. RGBA 与opacity
  9. SSIS hang with unhandle exception
  10. C# 常见集合之前的转换
  11. C语言volatile关键字
  12. 不相交集python实现
  13. 十六进制string转换UIColor -备用
  14. linux之SQL语句简明教程
  15. gulp + es6 + babel+ angular 搭建环境并实现简单的路由
  16. Oracle使用笔记(三)
  17. 微服务监控zipkin+asp.net core
  18. 分页-jquery.page.js插件在使用时重复触发“上一页”和“下一页”操作
  19. python ftp文件夹文件递归上传推送
  20. 阿里云Linux系统基线检查优化

热门文章

  1. VR中的“寻路(wayfinding)”
  2. 虚拟现实研究经典问卷Presence Questionnaire (PQ) 详细介绍
  3. IDEA 学习笔记之 1.5已经过时问题
  4. UVA - 11400 Lighting System Design
  5. Mac 10.14在新窗口中打开文件夹
  6. 引入flask_cache时出现ModuleNotFoundError: No module named &#39;flask.ext&#39;
  7. How to Get What You Want 如何得到你想要的
  8. Vue的介绍及安装和导入
  9. Jenkins构建Jmeter项目之源代码管理(SVN)
  10. 如何在项目中使用Spring异步调用注解@Async