1.问题描述

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

2.动态规划or贪心算法

动态规划:用来求解最优性质的解,将原问题划分为若干个子问题,先求解子问题的解,由子问题的解求出原问题的解。这些子问题往往不互相独立,所以我们用一个表(在具体代码中经常用数组)来存储子问题的解避免重复求解。动态规划需要满足的条件为最优子结构性质即问题的最优解所包含的子问题的解也是最优的。同时需要满足子问题的重叠性和无后效性即某状态以后的过程不会影响以前的状态,只与当前状态有关。

贪心算法:同样用来求解具有最优性质的解,总是做出当前状态下的最优选择。希望得到的最终结果也是最优的。贪心算法求解最优解的条件有两个:贪心选择性质——问题的最优解可以通过局部最优解得到;最优子结构性质。

动态规划和贪心算法的主要区别在于动态规划采用自底向上的方式求解问题,贪心算法则是采用自顶向下的方法进行求解,以迭代方式继续做出贪心选择,将问题规模变为规模更小的自问题。

言归正传,石子合并问题是否可以采用贪心算法?以求得最小合并数为例,如果采用贪心算法,每次做的贪心选择为总是合并两个相邻的石子个数最小的两堆。假如有五堆石子数分别为:8 7 6 8 。

第一次合并:8 7 6 8 。得分13

第二次合并:8 13 8 。得分13+ 21

第三次合并:21 8。得分13+21+29

不采用贪心算法:

第一次合并:8 7 6 8。得分15

第二次合并:15 6 8。得分15+14

第三次合并:15 14。得分15+14+29.(PS 最后一次得分总是石子总数sum,以后求解会用到)

所以该问题求解不适用与贪心算法,其实贪心算法适用的问题不是很广泛,比较典型的有活动安排问题,线段覆盖问题,数字组合问题等。

3.采用动态规划求解

动态规划算法的求解步骤分为:划分阶段——>确定状态和状态变量——>找出状态转移方程——>找出递归结束条件。

对于石子合并问题的问题阶段可分为:

当合并的石子为一堆时候:分数为0

当合并的石子为两堆时候:合并分数为相邻两堆石子的个数之和

当合并的石子为三堆时候:合并分数为min(第i堆石子与第i+1石子合并的分数+三堆石子总数,第i+1堆石子与第i+2石子合并的分数+三堆石子总数);

...

状态变量:m[i][j]第i堆至第j堆石子合并时候的分数,stone[i]表示第i堆石子个数

状态转移方程:m[i][j]=min(m[i][k]+m[k+1][j]+sum);sum表示第i堆石子至第j堆石子总数,也是最后一次合并的分数

4.代码实现

#include

#include

#define N 1000

using namespace std;

//求最小合并堆数目

//p[] 代表石头数目数组,n表示石堆数目

int minNumber(int p[N],int n)

{

int i=1,j=1,k=1;//用来计数

//定义二维数组m[i][j]来记录i到j的合并过程中的最少石子数目

int **m;

m=new int* [n];

for(i=1;i<=n;i++)

{

m[i]=new int[n];

}

for(i=1;i<=n;i++)

{

for(;j<=n;j++)

m[i][j]=-1;

}

int min=0;//记录合并最小值

//单独合并

for(i=1;i<=n;i++)

m[i][i]=0;

//相邻两堆石子合并

for(i=1;i<=n-1;i++)

{

j=i+1;

m[i][j]=p[i]+p[j];

}

//相邻三堆至最后的n堆

for(k=3;k<=n;k++)

{

int sum=0;//记录k堆石子总数

for(i=1;i<=n-k+1;i++)

{

j=i+k-1;//记录相邻r堆石子(第i个石子至第j个石子)合并

//先求得这k堆石子的总数

for(int x=i;x<=j;x++)

sum+=p[x];

//第一种情况

m[i][j]=m[i+1][j]+sum;

//计算i到k和k+1到j堆合并时候最小合并值,选择最小值

for(int r=i+1;r<=j-1;r++)

{

int t=m[i][r]+m[r+1][j]+sum;

if(t

m[i][j]=t;

}

}

}

return m[1][n];

}

//求最大合并值

int maxNumber(int p[],int n)

{

//记录生成最大合并值的过程中,从i到j合并的最大合并至

int i=1,j=1,k=1;//用来计数

int **m;

m=new int* [n];

for(i=1;i<=n;i++)

{

m[i]=new int[n];

}

for(i=1;i<=n;i++)

for(;j<=n;j++)

m[i][j]=-1;

int max=0;

//单独组合

for(i=1;i<=n;i++)

m[i][i]=0;

//两两组合

for(i=1;i<=n-1;i++)

{

j=i+1;

m[i][j]=p[i]+p[j];

}

//相邻三堆至第n堆组合时

for(k=3;k<=n;k++)

{

for(i=1;i<=n-k+1;i++)

{

int j=i+k-1;

int sum=0;

for(int r=i;r<=j;r++)

sum+=p[r];

m[i][j]=m[i+1][j]+sum;

for(k=i+1;k

{

int t=m[i][k]+m[k+1][j]+sum;

if(t>m[i][j])

m[i][j]=t;

}

}

}

return m[1][n];

}

int main()

{

int stone[N];

int min = N;

int max = 0;

int n;

int i = 1,j=1;

ifstream input("input.txt");

ofstream output("output.txt");

input >> n;

while (!input.eof())

{

input >> stone[i];

i++;

}

min = minNumber(stone, n);

max = maxNumber(stone, n);

for (; i <= n - 1; i++)

{

int min_temp = 0;

int max_temp = 0;

int temp = stone[1];

for (int k = 2; k <= n; k++)

{

stone[k - 1] = stone[k];

}

stone[n] = temp;

min_temp = minNumber(stone, n);

max_temp = maxNumber(stone, n);

if (min_temp

min = min_temp;

if (max_temp > max)

max = max_temp;

}

output <

output <

system("pause");

}

石子合并问题java_动态规划求石子合并问题相关推荐

  1. 动态规划石子排序java_动态规划之石子归并

    题目:有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量 和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输 ...

  2. 有n堆石子,每次取出两堆合成一堆,每堆石子的个数即为合并石子所需要耗费的体力,求出合并所有石子堆所需要耗费的最小体力

    有n堆石子,每次取出两堆合成一堆,每堆石子的个数即为合并石子所需要耗费的体力,求出合并所有石子堆所需要耗费的最小体力 典型的贪心题,即每次取出数量最少的两堆石子合并. 举个例子来说,假如有5堆石子,石 ...

  3. python list合并_python基础===两个list合并成一个dict的方法

    def Run(): list2 = [, , , , ]; list3 = ["a", "b", "c", "d",& ...

  4. pandas使用pd.concat纵向合并多个dataframe实战:纵向合并(ignore_index参数)、为纵向合并的多个dataframe设置标识符指定数据来源(通过字典方式设置数据来源键)

    pandas使用pd.concat纵向合并多个dataframe实战:多个dataframe的纵向合并(ignore_index参数).为纵向合并的多个dataframe设置标识符指定数据来源(通过字 ...

  5. Python将两个图像合并成一个图像(横向合并)

    Python将两个图像合并成一个图像(横向合并) 目录 Python将两个图像合并成一个图像(横向合并) #原始图像

  6. mysql多行合并成一行_数据文件合并与拆分

    [摘要] 本文介绍将多个文本文件和 Excel 文件合并成一个文件,或者将一个文件拆分成几个小文件时,如何处理会遇到的几种情况,并用 esProc SPL 举例实现. 在数据处理业务中,经常要把文件结 ...

  7. wps合并所有sheet页_Python一键合并上千个Excel表,一天的工作量一小时搞定!下班...

    一.老板的需求总是莫名奇妙 老板需求:一天老板说,嘿!放牛娃,将这些excel表合并到一个总表里,下班前交给我 老板话刚讲完,我心里就想,这还不简单么,excel不就是有合并表的功能么!!简单的要死! ...

  8. python两列字符串合并_python两列字符串如何合并?

    python两列字符串如何合并?,字符串,变量,方法,语句,就没 python两列字符串如何合并? python两列字符串如何合并? python两列字符串合并的方法: 1.在很多情况下,我们都需要合 ...

  9. shell换行合并多个文件_如何合并多个pdf文件?这里有合并PDF最简单的方法

    如何合并多个pdf文件?今天在整理一些PDF文件的时候,由于文件的数量比较多,我就想着将这些PDF文件合并起来,好在平时也了解了一些PDF合并的方法,很快就完成了文件的合并.想到应该还有很多朋友还不知 ...

最新文章

  1. SAP MIGO 发货批次确定界面批次可用数量无穷大问题之对策
  2. 从无到有<前端异常监控系统>落地
  3. Nginx+tomcat负载均衡session问题解决
  4. 从Exchange 通往Office 365系列(十六)添加域名到Office 365
  5. Java-OpenCV(一)准备工作
  6. Destoon数据库配置文件在哪_SpringBoot中yml配置文件说明和一些常用配置项说明
  7. 微软在线实验室启用谷歌的reCAPTCHA,我们又丢失了一个好东东
  8. vue 实现图片预览放大以及缩小
  9. 大革命修改后无法连接服务器,刺客信条大革命常见问题解决方法 中文设置教学...
  10. Halcon测量圆直径(半径)的方法之暴力拟合法 vs 测量工具法
  11. (17)全民小视频引流脚本模块化开发11-关注用户的粉丝By飞云脚本学院
  12. 科普:卡他妈滤波_拔剑-浆糊的传说_新浪博客
  13. Android 交互动画的统一实践
  14. 37d43641ef34f1a8a47c803dcf5a13793e3b9fef
  15. 解决Macm苹果笔记本电脑白屏
  16. git版本管理,有这一篇就够了(后端开发人员必备技能)
  17. 两年网罗13位扫地僧,阿里达摩院最新架构完整曝光
  18. oracle表空间查不到,Oracle 有的表查不到归属表空间
  19. PRL学习(priority roaming list 优先漫游列表)
  20. 空当接龙 java,VBA解决Windows空当接龙的617局

热门文章

  1. CDP科普:客户数据中台(CDP)是什么?
  2. java实现HTTPS单向认证TLS指定加密套件(文章很详细,好文章!)
  3. 第六章、Tiny4412 U-BOOT移植六 Nand Flash源码分析
  4. 妹子说头像爬的太慢?升级到多线程程序爬取头像
  5. java中特殊符号怎么校验_校验中文、空格和特殊符号的方法
  6. 【数据结构笔记】将两个递增的有序链表合并为一个递增的有序链表
  7. 中国人民大学计算机拟录取,2016年中国人民大学信息学院硕士研究生拟录取名单...
  8. 数据链路层的基本功能简单总结
  9. HMS Core AR Engine 2D图片/3D物体跟踪技术 助力打造更智能AR交互体验
  10. 小米蓝牙键盘怎么连接_小米2手机连接使用蓝牙键盘和蓝牙鼠标教程(原创)