博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
计蒜课中沙子的质量(动态规划)感想
阅读量:5037 次
发布时间:2019-06-12

本文共 2296 字,大约阅读时间需要 7 分钟。

设有N堆沙子排成一排,其编号为1,2,3,…,N(N< =300)。每堆沙子有一定的数量,可以用一个整数来描述,现在要将这N堆沙子合并成为一堆,每次只能合并相邻的两堆,合并的代价为这两堆沙子的数量之和,合并后与这两堆沙子相邻的沙子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同,如有4堆沙子分别为  1    3    5    2  我们可以先合并1、2堆,代价为4,得到4  5  2  又合并  1,2堆,代价为9,得到9  2  ,再合并得到11,总代价为4+9+11=24,如果第二步是先合并2,3堆,则代价为7,得到4  7,最后一次合并代价为11,总代价为4+7+11=22;

问题是:找出一种合理的方法,使总的代价最小。输出最小代价。

输入格式:

第一行一个数N表示沙子的堆数N。 第二行N个数,表示每堆沙子的质量。  < =1000

输出格式:

合并的最小代价

样例输入

41 3 5 2

样例输出

22

 

这道题目用到了算法中的动态规划,而在此我要将自己对这道题目的感想写到这里。

动态规划问题在我看来,用简单的话去说就是将每一步的值记录下来然后在处理大问题的时候直接将小问题的结果拿来用就可以。

而递归问题就是便利所有情况,然后从所有情况中找出最优的解。

这里我放出来源码:

#include
#include
using namespace std;int min(int x,int y){ if(x
>n; for(int i=1;i<=n;i++) { cin>>a; s[i]=s[i-1]+a; f[i][i]=0; } for(int r=2;r<=n;r++) for(int i=1;i+r-1<=n;i++) { int k=i+r-1,t=s[i+r-1]-s[i-1]; f[i][k]=f[i][i]+f[i+1][k]+t; for(int j=i+1;j<=k;j++) f[i][k]=min(f[i][k],f[i][j]+f[j+1][k]+t); } cout<
<

 

在这个问题中,我们应该如何利用动态规划的思想呢?

int MatrixChain(int n,int ss[]){        for(int i=1;i<=n;i++)m[i][i]=0;    for(int r=2;r<=n;r++)        for(int i=1;i<=n-r+1;i++){            int t = ss[i+r-1]-ss[i-1];            int j = i+r-1;            m[i][j] = m[i][i]+m[i+1][j]+t;            b[i][j] = i;             for(int k=i+1;k

 

在这段代码中,我们创建m[i][j]数组来记录每一步的数值,在主函数中“ss[i+1] = ss[i] + p[i]”语句是记录前n个数的和。例如:输入1 3 5 7。ss[1] = 1   ss[2]=1+3  ss[3] = 1+3+5......

(为何要记录这个呢?这个我们下面讲)

之后使用for(int i=1;i<=n;i++)m[i][i]=0; 将二维数组的主对角线上的值都设置为0(在m矩阵中,横纵坐标ij分别表示第i个数到j个数,而m内存的值表示i到j的最优情况下的最优解)

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

for(int i=1;i<=n-r+1;i++)这里,我们使用两重循环,按照主对线的方向从左到右逐层计算m数组,m[i][j] = m[i][i]+m[i+1][j]+t;这时候我们要看题,题目要让 我们对各个数相加,所以我们将大问题[i][j]分解为[i+1][j]与[i][i]。因为我们分解问题后还要将这几个数在加一下,所以这时候t就有了它的作用。例如(1,2,3,4    我们要求1—3的值,这时候,m[i][i]=1  m[i+1][j] = 2+3   而t=1+2+3 这里这个t就是前面我们提到的ss[3]-ss[0](t = ss[i+r-1]-ss[i-1]))这个时候我们就从小问题开始逐层填充这个二维数组,后面的问题要用到前面的数据。

在最后,因为我们第一次得到的s[i][j]并不一定是最优解,所以这个时候我们要使用

for(int k=i+1;k<j;k++){

int w = m[i][k]+m[k+1][j]+t;
if(m[i][j]<w){
m[i][j] = w;b[i][j] = k;
}
}

这个函数中我们截取i到j中任意一个数k,求所有情况中最优的解,然后覆盖原来的数组。将截断的点放在b[i][j]中。

到程序结束后,我们会得到两个二维数组,一个里面放着i到j的最优解的值,一个放着最优解的断点位置。

 

 

 

这个算法就是这样,第一次写算法的感想。。。。以后还是多努力吧,毕竟算法渣。。。。

Come on!                                                                               -----------------------Creat By Pinging

 

 

转载于:https://www.cnblogs.com/Pinging/p/7684638.html

你可能感兴趣的文章
where,having与 group by连用的区别
查看>>
【MySQL】MySQL锁和隔离级别浅析二 之 INSERT
查看>>
Oracle T4-2 使用ILOM CLI升级Firmware
查看>>
4.14上午
查看>>
数据分析 -- 白话一下什么是决策树模型(转载)
查看>>
Java SPI机制原理和使用场景
查看>>
web前端java script学习2017.7.18
查看>>
删除TXPlatform
查看>>
LaTex:图片排版
查看>>
并发访问超时的问题可能性(引用)
查看>>
中小团队基于Docker的Devops实践
查看>>
利用python打开摄像头并保存
查看>>
System函数的使用说明
查看>>
Selenium-测试对象操作之:获取浏览器滚动条滚动距离
查看>>
Linux下MySQL数据库安装与配置
查看>>
Extjs String转Json
查看>>
oracle入门(4)——少而常用的命令
查看>>
打印机设置(PrintDialog)、页面设置(PageSetupDialog) 及 RDLC报表如何选择指定打印机...
查看>>
Java 虚拟机部分面试题
查看>>
二叉树的遍历问题总结
查看>>