裝載問題(回溯法)


1、問題

有n個集裝箱要裝上2艘載重量分別為c1和c2的輪船,其中集裝箱i的重量為wi,且∑wi <= c1 + c2。

問是否有一個合理的裝載方案,可將這n個集裝箱裝上這2艘輪船。如果有,找出一種裝載方案。

2、解析

c1和c2是相互獨立的,即如何在c1或者c2上,放置物品是互不干擾的。
但是假如先在c1上放置貨物,則因剩下的貨物不同,會使c2上裝載的貨物的情況發生變化。
因此,為了保證c1上裝載的情況,滿足c1和c2將所有的貨物都裝下,c1上應該盡可能的多放物品。

3、設計

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int num=100;
 4 int n,c1,c2,w[num];// n個集裝箱,A,B貨輪載重量分別為C1,C2,W[i],第i個集裝箱的重量
 5 int cw,bw,rw;//cw,當前集裝箱貨物重量;bw,最優載重重量,rw,剩余集裝箱重量;
 6 int x[num],bx[num];//x[],A貨輪的當前結果;bx[],A貨輪的最優結果;
 7 void BackTrack(int i) {
 8     //處理完了前n個集裝箱;
 9     if(i>n){
10         if(cw>bw){//cw,目前A中裝了cw重量的集裝箱;
11         //更新最優解;
12             bw=cw;
13             for(int i=1;i<=n;i++) bx[i]=x[i];
14         }    
15         return;
16     }
17     //rw表示處理完第i個之后(選或不選),還剩下rw-w[i]重量的集裝箱未處理;
18     rw-=w[i];
19     if(cw+w[i]<=c1){//cw,第i個貨箱之前的重量 + 第i個貨箱小於A的最大重量C1;
20         cw+=w[i];//加上
21         x[i]=1;//標記i被選
22         BackTrack(i+1);
23         cw-=w[i];//減去重量
24         x[i]=0;//撤銷標記;
25     }
26     //不選擇第i個物品的話;
27     //if cw:表示[1:i)的數據  rw:表示(i,n]的數據 ,不包括第i個的數據
28     //如果不包括第i的數據的和(cw+rw) 大於  目前最優解bw,則可以遞歸下去;
29     if(cw+rw > bw){
30         x[i]=0;
31         BackTrack(i+1);
32     }
33 
34     //處理完第i個物品當前的情況了;
35     //因為再上一層,有兩種情況;
36     //1;選擇第i物品;
37     //2:不選擇第i個物品
38     //如果目前處理的是上一層第1種情況,那么我們就有必要加上這個w[i];
39     //否則會影響上一層處理第2種情況;
40     rw+=w[i];
41     return ;
42 }
43 int main(){
44     scanf("%d%d%d",&n,&c1,&c2);
45     for(int i=1;i<=n;i++) {
46         scanf("%d",&w[i]);
47         rw+=w[i];//rw表示目前最優集裝箱的剩余重量;
48     }
49     //遞歸回溯
50     BackTrack(1);
51     //bw表示A貨輪裝下的貨物重量;剩余的重量 > B可以放下的最多,則不可;
52     if(rw-bw>c2){
53         printf("沒有裝載方案\n");
54     }else{
55         printf("貨輪A:\n");
56         for(int i=1;i<=n;i++) {
57             if(bx[i]) {
58                 printf("%d ",i);
59             }
60         } 
61         printf("\n貨輪B:\n");
62         for(int i=1;i<=n;i++) {
63             if(0==bx[i]) {
64                 printf("%d ",i);
65             }
66         } 
67     }
68     return 0;   
69 }

4、分析

最壞情況要遍歷圖中所有結點,算法的時間復雜度為O(2")。因為,葉子結點有2",每個結點要計算機裝載量以判斷是否回溯。

5、源碼

https://github.com/ChenyuWu0705/Algorithm-Analyze-and-Design/blob/main/loan.cpp


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM