算法描述

两艘船各自可装载重量为c1,c2,n个集装箱,各自的重量为w[n],设计一个可以装载的方案,使得两艘船装下全部集装箱

算法思路

  1. 将第一艘船尽量装满(第一艘船放的集装箱的重量之和接近c1),剩余的集装箱放入第二艘船,若剩余的集装箱重量之和大于第二艘船,则无解

  2. 定义一个一维数组,a[n] 存放对应的集装箱的重量

  3. 定义一个数组,m[i][j]表示第一艘船还可装载的重量j,可取集装箱编号范围为i,i+1...n的最大装载重量值

    例如 现在有3个集装箱 重量分别为9,5,3,即a[1]=9 a[2]=5 a[3]=3

    m[1][2]=0 可装载重量为2,此时上述的三个集装箱都不能装入,所以为最大可装载重量为0

    m[1][3]=m[1][4]=3 可装载重量为3或者是4的时候,都是只能装入重量为3的那个集装箱,所以最大可装载重量为3 `

    实际上,这里的3=a[3]+m[1][2],是一个递推的关系,具体看下面`

  4. m[i][j]分下面两种情况
    • 0<=j<a[n] (当可装载重量j小于第n个集装箱的重量w[n],此时就不能往船上装此集装箱) m[i][j] = m[i+1][j]

    • j>=a[n]可装载重量j大于或等于第n个集装箱的重量w[n]),此时剩余的可装载重量为j-a[n](装入了此时的集装箱),最大的可装载重量为m[i+1][j-w[n]]+w[n]

      但是我们是需要最大的可装载重量,所以得与如果不将当前集装箱装入的那种情况m[i+1][j]进行比较

      m[i][j]=Math.max(m[i+1][j],m[i+1][j-a[n]+a[n]])

  5. 上面我们就获得了一个关于m[i][j]的递推关系,我们通过逆推获得全部的数值

    • 初始值

      m[i][j]=0 这里的i=n j从0到a[n] 这里的a[n]是第n个集装箱重量(最后一个集装箱的重量)

      这里的赋值其实就是上述m[i][j]两种情况的第一种情况,最后一个集装箱的重量大于可装载重量,不装载此集装箱,所以最大可装载重量为0,

      m[i][j]=a[n] 这里的i=n j从a[n]到c1 这里的a[n]是第n个集装箱的重量(最后一个集装箱的重量)

      这里的意思为当可装载重量j只要都是大于最后一个集装箱的重量a[n],即可装入此集装箱,所以最大可装载重量等于装入的集装箱的重量

    • 开始逆推

      使用上述的递推公式进行逆推

        for (int i = n; i >= 1 ; i--) {for (int j = 1; j <=c1; j++) {if(j>=a[i]){m[i][j] = Math.max(m[i+1][j],m[i+1][j-a[i]]+a[i]);}else{m[i][j]=m[i+1][j];}}}
  6. 之后再进行输出,输出第一艘船的装载方案,输出第二艘船的装载方案

算法实现

    System.out.println("输入第一艘船可装载重量c1:");Scanner scanner = new Scanner(System.in);int c1 = scanner.nextInt();System.out.println("输入第二艘船可装载重量c2:");int c2 = scanner.nextInt();System.out.println("输入集装箱个数n:");int n = scanner.nextInt();int[] a = new int[n+1];//使用一维数组存放集装箱重量System.out.println("依次输入集装箱的重量");for (int i =1; i < n+1; i++) {a[i] = scanner.nextInt();}int sum = 0;//集装箱重量总和for (int i = 0; i < a.length; i++) {sum=sum+a[i];}//超重情况if(sum>c1+c2){System.out.println("集装箱重量之和大于两艘船可装载重量,题目无解");return;//结束程序}int[][] m = new int[100][100];//m[i][j]表示第一艘船还可装载的重量j,可取集装箱编号范围为i,i+1...n的最大装载重量值//赋初始值,由于是逆推,所以从末尾开始//可装载重量j小于第n个集装箱重量a[n],不装此集装箱,赋值为0for (int j = 0; j < a[n]; j++) {m[n][j] = 0;}//可装载重量j大于或等于第n个集装箱重量a[n],装载此集装箱,此时刻最大装载重量值为a[n]for (int j = a[n]; j <=c1 ; j++) {m[n][j]=a[n];}//关键逆推代码for (int i = n; i >= 1 ; i--) {for (int j = 1; j <=c1; j++) {if(j>=a[i]){m[i][j] = Math.max(m[i+1][j],m[i+1][j-a[i]]+a[i]);}else{m[i][j]=m[i+1][j];}}}int maxc1 = m[1][c1];//最大可装载重量System.out.println("maxc1="+maxc1);if(maxc1>sum-c2){int cw = m[1][maxc1];int sw,i;//输出第一艘船的装载System.out.println("第一艘船装载:");for (sw=0,i=1;i<=n;i++){if(m[i][cw]>m[i+1][cw]){cw = cw-a[i];sw=sw+a[i];//统计sw,sw的最终结果与maxc1相等System.out.print(a[i]+"     ");a[i]=0;//装载当前的集装箱}}System.out.print("("+sw+")");System.out.println("");//输出第二艘船的装载System.out.println("第二艘船装载:");for(sw=0,i=1;i<=n;i++){//已装载在第一艘船的集装箱a[i]都已经为0了,只需要将不为0的那些集装箱装入第二艘船即可if(a[i]!=0){System.out.print(a[i]+"     ");sw=a[i]+sw;}}System.out.println("("+sw+")");}else{System.out.println("无解");}

结果

转载于:https://www.cnblogs.com/kexing/p/9951554.html

算法学习——动态规划之装载问题相关推荐

  1. 数据结构与算法学习⑥(动态规划 题解 背包和打家劫舍问题)

    数据结构与算法学习⑥(动态规划 动态规划 1.初识动态规划 1.1.从贪心说起 1.1.1.贪心的特点 1.1.2.贪心的局限性 1.1.3.贪心失效后怎么办 1.1.4.从最优化问题到递归 1.2. ...

  2. 算法学习--动态规划与贪心算法

    动态规划与贪心算法都是一种递推算法,都是用局部最优解来推导全局最优解:是对遍历解空间的一种优化:当问题具有最优子结构时,可以用动态规划来解决,而贪心算法是动态规划的特例 动态规划 1. 动态规划的思想 ...

  3. C++算法学习(动态规划算法)

    动态规划算法 1.目标 2.方法 3.过程 4.例题 (1)[力扣:5. 最长回文子串](https://leetcode-cn.com/problems/longest-palindromic-su ...

  4. 算法学习-动态规划,纸老虎打倒他(持续更新中)

    文章目录 基础知识 线性DP 相关题目 45.跳跃游戏II 70.爬楼梯 746.使用最小花费爬楼梯 62.不同路径 63.不同路径2 343.整数拆分 96.不同的二叉搜索树 91.解码方法 119 ...

  5. 算法学习-动态规划(二)

    文章目录 问题一:四维动态规划 算法伪代码 时间复杂度分析 问题二:类似矩阵链乘 算法伪代码 算法时间复杂度 问题三 问题四 算法伪代码 问题五 算法伪代码 问题五 问题六 问题七 问题一:四维动态规 ...

  6. 数字三角形路径最小值c语言题目,算法学习——动态规划之点数值三角形的最小路径...

    算法描述在一个n行的点数值三角形中,寻找从顶点开始每一步可沿着左斜或者右斜向下直到到达底端,使得每个点上的数值之和为最小 右图为一个4行的点数值三角形 算法思路接收用户输入行数n 使用一个二维数组a[ ...

  7. 算法学习 - 01背包问题(动态规划C++)

    动态规划 01背包 问题描述 求解思路 代码实现 放入哪些物品 代码 动态规划 我在上一篇博客里已经讲了一点动态规划了,传送门:算法学习 - 动态规划(DP问题)(C++) 这里说一下,遇到动态规划应 ...

  8. php算法学习,php算法学习之动态规划

    动态规划程序设计是对解最优化问题的一种途径.一种方法,最终问题的最优解可以通过前面子问题的最优解推导出来. 对于动态规划这个算法,自己学习的还不是很透彻,简单的总结自己学习的感受是: 动态规划思想中融 ...

  9. 图解算法学习笔记(九):动态规划

    目录 (1)背包问题 (2)最长公共子串 (3)小结 本章内容: 学习动态规划,它将问题分成小问题,并先着手解决这些小问题. 学习如何设计问题的动态规划解决方案. (1)背包问题 我们再看第八章的背包 ...

最新文章

  1. [Android] 基于 Linux 命令行构建 Android 应用(六):Android 应用签名
  2. 正则表达式——全部符号解释(详解)
  3. main函数的参数详解,它们是何时何处传入的?(main函数的参数值是从操作系统命令行上获得的)
  4. c语言设置程序自动执行,c语言如何设置程序进程执行优先权
  5. Vue过滤器的简单使用--实时显示格式化的时间
  6. jzoj3682-Points and Segments【模型转化,欧拉回路】
  7. 2017蓝桥杯省赛---java---A---4(方格分割)
  8. 最小二乘法,了解一下?
  9. sklearn 2.回归树
  10. “软下来”的苹果和小米能否拯救智能手机的焦虑? | 畅言
  11. (六)关于beetlsql版本(分支)的说明
  12. JavaScript中函数式编程的原理
  13. VC++/MFC学习笔记(二)
  14. C#获取当前时区转换方法
  15. 通过完美python注释,打印类的帮助文档
  16. html生成一维码,一维码条形码生成工具
  17. PC硬件设备配置介绍与选型参考
  18. 一键自动下载百度美女图片
  19. android手机为什么越用越卡
  20. android --拍照相册选取图片[兼容小米等其他手机]

热门文章

  1. 11届蓝桥杯青少年组C++全国赛高级组 六.编程实现:求阶乘(python3实现)
  2. 微信小程序,小游戏sockect报错修复集合
  3. 程序猿bug修改名句
  4. 操作系统课设之基于信号量机制的并发程序设计
  5. jvm类加载过程_JVM类生命周期概述:加载时机与加载过程
  6. Java工作笔记-判断文件是否被正在被写入
  7. Qt的信号槽机制介绍(含Qt5与Qt4的差异对比)
  8. Linux工作笔记-查看tcp与udp端口并对比Windows简单分析
  9. 【编译原理】:NFA转变为DFA的子集构造法
  10. JAVA和C++内部类