石子合并问题石子合并问题石子合并问题

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)相关推荐

  1. 【SSL】1597石子合并问题(环形)

    [SSL]1597石子合并问题(环形) Time Limit:1000MS Memory Limit:65536K Description 在一个圆形操场的四周摆放着n 堆石子.现要将石子有次序地合并 ...

  2. AcWing 1068. 环形石子合并(环形区间DP)

    AcWing 1068. 环形石子合并(环形区间DP) 一.问题 二.思路 三.代码 一.问题 二.思路 在讲解这道题之前,我们需要先掌握线性的区间DP问题,如果对于线性区间DP的解决方式还不了解的话 ...

  3. 算法分析 | 动态规划 | 石子合并问题

    一.问题描述 在一条直线上有n堆石子, 要求每次将相邻的两堆石子合成一堆,花费=两堆石子的总数 求最省总花费. 因为存在相邻的限制条件,不能使用贪心算法将每次最小的2堆合起来.遂使用动态规划 二.代码 ...

  4. 算法设计与分析——动态规划——石子合并问题

    1.石子合并问题 在一个圆形操场的四周摆放着n堆石子.现要将石子有序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.设计一个算法,计算出将n堆石子合并成 ...

  5. 【动态规划】石子合并 (ssl 2863)

    石子合并石子合并石子合并 Description 在一个操场上一排地摆放着N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.请设 ...

  6. 石子合并(动态规划DP)

    时限: 1000ms 内存限制:10000K  总时限:3000ms 描述: 在一个圆形操场的四周摆放着n堆石子(n<= 100),现要将石子有次序地合并成一堆.规定每次只能选取相邻的两堆合并成 ...

  7. 动态规划经典题之石子合并

    题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分 试设计出1个算法,计算出将N堆石子合并成1堆 ...

  8. AcWing 1068. 环形石子合并

    AcWing 1068. 环形石子合并 题意: n堆石头围成一个圈,然后将相邻两堆合并成新的一堆,得分为新的一堆的石头数 问最高得分合最低得分 题解: 很简单,区间dp的模板题 和这个题一样 状态转移 ...

  9. 动态规划 —— 区间 DP —— 石子合并三讲

    石子合并问题是最经典的 DP 问题,其有如下3种题型: [任意合并] 1.问题: 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为新合成的一堆石子的数量.求 ...

最新文章

  1. 原创:去繁存简,回归本源:微信小程序公开课信息分析《一》
  2. Medoo入门:安装和配置-Medoo使用指南
  3. 创智播客微服务_【传智播客】JavaEE在职加薪课
  4. 记录部署hue在k8s上
  5. 【OpenCV】图像几何变换:旋转,缩放,斜切
  6. 678. 有效的括号字符串
  7. Martin Odersky Scala编程公开课 第二周作业
  8. 安卓应用安全指南 5.6.1 密码学 示例代码
  9. mycat分库分表建索引
  10. [译] Bulma: 2018年你应该关注的CSS框架
  11. Vue源码:抽象语法树
  12. 交通流理论 第一章 绪论
  13. 转载——巨详细的MD5加盐,大佬详解
  14. 使用planetaryjs插件实现3维地球仪效果
  15. flashfxp连接失败,flashfxp连接失败怎么办
  16. 每天下午5点使用计算机结束时断开终端的连,在每天下午5点使用计算机结束时断开终端的连接属于()...
  17. CentOS 5遇到Partition table entries are not in disk order
  18. 【数据处理】正则匹配指定字符传后面的字符
  19. 网络不稳定 网速忽高忽低,ping值忽高忽低的解决办法 无线网出现问题解决
  20. 如何实现罗克韦尔PLC AB1756的远程监控数据采集?

热门文章

  1. 前端跨域请求get_前端实现跨域访问
  2. 2020计算机单招的大专,2020专科和单招的区别
  3. python自然语言处理_python
  4. Java使用TCP实现群聊 聊天室(多线程和tcp的使用)
  5. [数据结构-严蔚敏版]P46栈的顺序存储表示
  6. C++set容器-构造和赋值
  7. 利用链表实现可合并堆(算法导论第三版思考题10-2)
  8. 计算机网络原理第一章习题3-24 3-25
  9. 批量将PPM格式图片转化为JPG格式
  10. 经典排序算法(12)——总结