回溯法,回溯法解裝載問題
一、回溯法有“通用的解題法”之稱,可以系統的搜尋一個問題的所有解或任一解。它在問題的解空間中按深度優先策略,從根節點出發,搜尋解空間樹。演算法搜尋至解空間樹的任一節點時,先判斷該節點是否包含問題的解,如果肯定不包含則跳過對以該節點為根的子樹的搜尋,回到其父節點回溯。否則,進入該子樹,繼續按深度優先策略搜尋。
利用回溯法解問題時一般按以下三步驟:
1)定義問題的解空間;
2)確定易於搜尋的解空間結構;
3)以深度優先策略搜尋解空間,並在搜尋過程中用剪枝函式避免無效搜尋;
二、回溯法應用——裝載問題
一批集裝箱共n個要裝上2艘載重量分別為c1和c2的輪船,其中集裝箱i的重量為Wi且W1+W2+……+Wn<=c1+c2;試確定一個合理的裝載方案使這n個集裝箱裝上這兩艘輪船。
#include<stdlib.h>
#include<stdio.h>
#include<iostream.h>
typedef int Status;
typedef int Type;
int n=0; //集裝箱數
Type *x=(Type*)malloc((50)*sizeof(Type));//當前解
Type *bestx=(Type*)malloc((50)*sizeof(Type));//當前最優解
Type c=0, //第一艘輪船的載重量
cw=0, //當前載重量
bestw=0, //當前最優載重量
r=0,
*w=(Type*)malloc((50)*sizeof(Type)); //集裝箱重量陣列
int Backtrack(int i)//搜尋第i層節點
{
int j_index;
/*如果到達葉結點,則判斷當前的cw,如果比前面得到的最優解bestw 好,則替換原最優
解。*/
if(i>n)
{
if(cw>bestw)
{
for(j_index=1; j_index<=n; j_index++)
bestx[j_index]=x[j_index]; bestw=cw;
}
return 1;
}
//搜尋子樹
r-=w[i];
if(cw+w[i]<=c)//搜尋左子樹,如果當前剩餘空間可以放下當前物品也就是,cw + w[ i ] <= c
{
x[i]=1;
cw+=w[i];//把當前載重 cw += w[ i ]
Backtrack(i+1);//遞迴訪問其左子樹,Backtrack( i + 1 )
cw-=w[i];//訪問結束,回到呼叫點, cw - = w[ i ]
}
if(cw+r>bestw)//搜尋右子樹
{
x[i]=0;
Backtrack(i+1);
}
r+=w[i];
}
Type* Initiate()
{
int index=1;
printf("輸入集裝箱個數:");
scanf("%d",&n);
printf("輸入輪船載重量:");
scanf("%d",&c);
while(index<=n)//陣列從1號單元開始儲存
{
printf("輸入集裝箱%d 的重量:",index);
scanf("%d",&w[index]);
index++;
}
bestw = 0;
cw = 0;
r = 0;
for(index =1;index <= n; index++)
r += w[index]; //初始時r 為全體物品的重量和
printf("n=%d c=%d cw=%d bestw=%d r=%d\n",n,c,cw,bestw,r);
for(index=1;index<=n;index++)
{
printf("w[%d]=%d ",index,w[index]);
}
printf("\n");
return w;
}
int main()
{
int i;
Initiate();
//計算最優載重量
Backtrack(1);
for(i=1;i<=n;i++)
{
printf("%d ",w[i]);
printf("%d\n",bestx[i]);
}
return bestw;
}