【动态规划】 石子合并问题(环形) (ssl 1597)
石子合并问题石子合并问题石子合并问题
Description
在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分。
编程任务:
对于给定n堆石子,编程计算合并成一堆的最小得分和最大得分。
Input
输入包括多组测试数据,每组测试数据包括两行。
第1 行是正整数n,1<=n<=100,表示有n堆石子。
第2行有n个数,分别表示每堆石子的个数。
Output
对于每组输入数据,输出两行。
第1 行中的数是最小得分;第2 行中的数是最大得分。
Sample Input
4
4 4 5 9
Sample Output
43
54
题目大意:
有n堆石子,围成一个环,可以将相邻的两堆合在一起,两堆的重量之和为你的分数,要求最大分数和最小分数
解题方法:
建议先做完石子合并(非环形)题解,再做此题,本体我们有两种方法:
方法一方法一方法一
我们先用一个二位数组f[i][j]来表示从第i对开始,后面的j个数的最小值(最大的用l),然后在后面复制一遍接下来就和石子合并差不多了
动态转移方程:
f[i][len]=min(f[i][len],f[i][k]+f[i+k][len−k]+s[i+len−1]−s[i−1])f[i][len]=min(f[i][len],f[i][k]+f[i+k][len-k]+s[i+len-1]-s[i-1])f[i][len]=min(f[i][len],f[i][k]+f[i+k][len−k]+s[i+len−1]−s[i−1])
l[i][len]=max(l[i][len],l[i][k]+l[i+k][len−k]+s[i+len−1]−s[i−1])l[i][len]=max(l[i][len],l[i][k]+l[i+k][len-k]+s[i+len-1]-s[i-1])l[i][len]=max(l[i][len],l[i][k]+l[i+k][len−k]+s[i+len−1]−s[i−1])
注释:
f[i][k]为前面,i+k是后面的开始,len-k是长度有len已经用了k,所以要减掉k,i+len-1是这一段的后面,因为第i个也要求,所以要减去i-1
#include<cstdio>
#include<iostream>
using namespace std;
int a[205],f[205][205],l[205][205],s[205],n,minn,maxx;
int main()
{memset(f,127/3,sizeof(f));scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%d",&a[i]);s[i]=s[i-1]+a[i];f[i][1]=0;}for (int i=n+1;i<=n*2;i++){s[i]=s[i-1]+a[i-n];//复制一遍f[i][1]=0;}for (int len=2;len<=n;len++)//长度for (int i=1;i<=n*2-len;i++)//前面的数,n-len+1+n-1=n*2-lenfor (int k=1;k<len;k++)//分界线{f[i][len]=min(f[i][len],f[i][k]+f[i+k][len-k]+s[i+len-1]-s[i-1]);//求最小的l[i][len]=max(l[i][len],l[i][k]+l[i+k][len-k]+s[i+len-1]-s[i-1]);//求最大的}minn=2147483647;for (int i=1;i<=n;i++){minn=min(minn,f[i][n]);//最小的maxx=max(maxx,l[i][n]);//最大的}printf("%d\n%d",minn,maxx);
}
方法二方法二方法二
我们不在后面加一段(f和l表示的一样),直接用mod的方法,超过你的直接从1开始往后,本做法详情看动态转移方程
动态转移方程
f[i][len]=min(f[i][len],f[i][k]+f[(i+k−1)modn+1][len−k]+fj(i,i+len−1));f[i][len]=min(f[i][len],f[i][k]+f[(i+k-1)modn+1][len-k]+fj(i,i+len-1));f[i][len]=min(f[i][len],f[i][k]+f[(i+k−1)modn+1][len−k]+fj(i,i+len−1));
l[i][len]=max(l[i][len],l[i][k]+l[(i+k−1)modn+1][len−k]+fj(i,i+len−1));l[i][len]=max(l[i][len],l[i][k]+l[(i+k-1)modn+1][len-k]+fj(i,i+len-1));l[i][len]=max(l[i][len],l[i][k]+l[(i+k−1)modn+1][len−k]+fj(i,i+len−1));
注释:
(i+k-1) mod n+1为什么不写成(i+k)mod n呢?因为当i+k=n时,结果为0,0不在我们的计算范围内,所以我们要用(i+k-1) mod n+1,用这种的话,当i+k=n时,结果为n。fj(i,i+len-1)为计算i到i+len-1之间的数
#include<cstdio>
#include<iostream>
using namespace std;
int a[105],f[105][105],l[105][105],s[105],n,minn,maxx;
int fj(int x,int y)
{if (y<=n) return s[y]-s[x-1];//没有超过nreturn fj(x,n)+fj(1,y-n);//分两段
}
int main()
{memset(f,127/3,sizeof(f));scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%d",&a[i]);s[i]=s[i-1]+a[i];f[i][1]=0;}for (int len=2;len<=n;len++)//长度for (int i=1;i<=n;i++)//前面的for (int k=1;k<len;k++)//分界线{f[i][len]=min(f[i][len],f[i][k]+f[(i+k-1)%n+1][len-k]+fj(i,i+len-1));//状态转移方程l[i][len]=max(l[i][len],l[i][k]+l[(i+k-1)%n+1][len-k]+fj(i,i+len-1));//状态转移方程}minn=2147483647;for (int i=1;i<=n;i++){minn=min(minn,f[i][n]);//求最小的maxx=max(maxx,l[i][n]);//求最大的}printf("%d\n%d",minn,maxx);
}
【动态规划】 石子合并问题(环形) (ssl 1597)相关推荐
- 【SSL】1597石子合并问题(环形)
[SSL]1597石子合并问题(环形) Time Limit:1000MS Memory Limit:65536K Description 在一个圆形操场的四周摆放着n 堆石子.现要将石子有次序地合并 ...
- AcWing 1068. 环形石子合并(环形区间DP)
AcWing 1068. 环形石子合并(环形区间DP) 一.问题 二.思路 三.代码 一.问题 二.思路 在讲解这道题之前,我们需要先掌握线性的区间DP问题,如果对于线性区间DP的解决方式还不了解的话 ...
- 算法分析 | 动态规划 | 石子合并问题
一.问题描述 在一条直线上有n堆石子, 要求每次将相邻的两堆石子合成一堆,花费=两堆石子的总数 求最省总花费. 因为存在相邻的限制条件,不能使用贪心算法将每次最小的2堆合起来.遂使用动态规划 二.代码 ...
- 算法设计与分析——动态规划——石子合并问题
1.石子合并问题 在一个圆形操场的四周摆放着n堆石子.现要将石子有序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.设计一个算法,计算出将n堆石子合并成 ...
- 【动态规划】石子合并 (ssl 2863)
石子合并石子合并石子合并 Description 在一个操场上一排地摆放着N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.请设 ...
- 石子合并(动态规划DP)
时限: 1000ms 内存限制:10000K 总时限:3000ms 描述: 在一个圆形操场的四周摆放着n堆石子(n<= 100),现要将石子有次序地合并成一堆.规定每次只能选取相邻的两堆合并成 ...
- 动态规划经典题之石子合并
题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分 试设计出1个算法,计算出将N堆石子合并成1堆 ...
- AcWing 1068. 环形石子合并
AcWing 1068. 环形石子合并 题意: n堆石头围成一个圈,然后将相邻两堆合并成新的一堆,得分为新的一堆的石头数 问最高得分合最低得分 题解: 很简单,区间dp的模板题 和这个题一样 状态转移 ...
- 动态规划 —— 区间 DP —— 石子合并三讲
石子合并问题是最经典的 DP 问题,其有如下3种题型: [任意合并] 1.问题: 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为新合成的一堆石子的数量.求 ...
最新文章
- 原创:去繁存简,回归本源:微信小程序公开课信息分析《一》
- Medoo入门:安装和配置-Medoo使用指南
- 创智播客微服务_【传智播客】JavaEE在职加薪课
- 记录部署hue在k8s上
- 【OpenCV】图像几何变换:旋转,缩放,斜切
- 678. 有效的括号字符串
- Martin Odersky Scala编程公开课 第二周作业
- 安卓应用安全指南 5.6.1 密码学 示例代码
- mycat分库分表建索引
- [译] Bulma: 2018年你应该关注的CSS框架
- Vue源码:抽象语法树
- 交通流理论 第一章 绪论
- 转载——巨详细的MD5加盐,大佬详解
- 使用planetaryjs插件实现3维地球仪效果
- flashfxp连接失败,flashfxp连接失败怎么办
- 每天下午5点使用计算机结束时断开终端的连,在每天下午5点使用计算机结束时断开终端的连接属于()...
- CentOS 5遇到Partition table entries are not in disk order
- 【数据处理】正则匹配指定字符传后面的字符
- 网络不稳定 网速忽高忽低,ping值忽高忽低的解决办法 无线网出现问题解决
- 如何实现罗克韦尔PLC AB1756的远程监控数据采集?