日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法学习——动态规划之装载问题

發布時間:2025/3/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法学习——动态规划之装载问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

算法描述

兩艘船各自可裝載重量為c1,c2,n個集裝箱,各自的重量為w[n],設計一個可以裝載的方案,使得兩艘船裝下全部集裝箱

算法思路

  • 將第一艘船盡量裝滿(第一艘船放的集裝箱的重量之和接近c1),剩余的集裝箱放入第二艘船,若剩余的集裝箱重量之和大于第二艘船,則無解

  • 定義一個一維數組,a[n] 存放對應的集裝箱的重量

  • 定義一個數組,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],是一個遞推的關系,具體看下面`

  • 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]])

  • 上面我們就獲得了一個關于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];}}}
  • 之后再進行輸出,輸出第一艘船的裝載方案,輸出第二艘船的裝載方案

  • 算法實現

    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

    總結

    以上是生活随笔為你收集整理的算法学习——动态规划之装载问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。