問題描述
問題描述:設有n件體積分別爲w1、w2……wn的物品和一個能裝載總體積爲T的揹包,要求從n件物品中挑選若干件物品,其總體積之和恰好裝滿揹包。若能,則揹包有解,否則無解;
求解方法:先將n件物品順序排列,依次裝入揹包,每裝入一件即檢查當時揹包物品體積是否超過T,若裝入該物品後不超過揹包容量T,則裝入,否則棄之取下一個,直到裝滿揹包爲止。若在裝入若干物品後背包未滿,但又無其他物品可選時,說明已裝入揹包內的物品不合適,需從揹包中取出最後裝入的物品,繼續在其他未裝入的物品中挑選,如此重複知道裝滿揹包(有解)或者無物品可選(無解);
輸入輸出樣例:若T=10;W=(4,7,3,5,4,2)時,執行程序,輸出結果爲Wi=(4,4,2)。
設計思路
設計思路:設一維數組W[1:n]用來存放n件物品的體積,棧S[1:n]用來存放放入揹包內的物品的序號,T爲揹包能容納的體積,i爲待選物品序號。每進棧一件物品,就從T中減去該物品的體積,若T-W[i]>=0,則該物品可選,若T-W[i]<0,則該物品不可選,若i>n,則需退棧,若此時棧空,則說明無解。
數據結構:W[1:n]:存放n件物品的體積。S[1:n]:存放放入揹包內物品的序號。
算法描述:
PACK( T, n, W, S, top )
top<-0; i<-1
while(T>0) and (i<=n) do
if (T-W[i]=0) or (T-W[i])>=0) and (i<n) then
{top<-top+1; s[top]<-i; T<-T-W[i]}
If (T=0) then {“揹包有解“ return”}
else { if(i=n) and (top>0) then //取出棧頂物品//
{ i<-s[top]; top<-top-1,T<-T+W[i] }
i<-i+1//準備挑選下一件物品// }
end ( while )
“揹包無解“ return
測試用例及結果說明
揹包容量:T=10;
物品質量:W[6]={4, 7, 3, 5, 4, 2 };
測試結果:揹包裝的物品質量爲:4,4,2;
設計及測試過程
第一步:提出問題;
第二步:問題轉換;
第三步:算法構思;
第四步:僞碼描述;
第五步:代碼編寫;
第六步:代碼測試;
第七步:代碼修正;
參考書籍:《計算機軟件技術基礎》 清華大學出版社 第三版
評價和改進
算法優點:簡潔易懂。
算法缺點:採用回溯求解,效率較低。
功能優點:能夠準確找到揹包解(揹包有解時)。
功能缺點:找到揹包第一個解後即退出,不能找到全部解。
功能拓展:在遍歷所有可能解之前不結束程序,記錄解的值之後繼續執行程序知道找出所有解。
思考的問題:如何輸出所有解。
附:源程序
#include <iostream>
#define N 7
using namespace std;
int main()
{
int i, w[N], s[N],vm[N], C, top, j, vi[N], V=0, Vmax=0, vitop;
cout<<"請輸入揹包容量"<<endl;
cin>>C;
cout<<"請輸入6件物品體積及其價值"<<endl;
for(i=0;i<N-1;i++)
{
cout<<"第"<<i+1<<"件物品的體積爲 ";
cin>>w[i];
cout<<"價值爲 ";
cin>>vi[i];
cout<<endl;
}
w[6]=0;
vi[6]=0;
top=0;
i=0;
while(C>=0&&i<N)
{
cout<<"1>"<<endl;
if(C-w[i]>=0&&i<N-1)
{
top++;
s[top]=i;
C=C-w[i];
V=V+vi[i];
}
if(V>Vmax)
{
Vmax=V;
vitop=top;
cout<<" vitop="<<vitop<<endl;
for(j=1;j<=top;j++)
vm[j]=s[j];
}
else
{
if(i==N-1&&top>0)
{
i=s[top];
top--;
C=C+w[i];
V=V-vi[i];
}
}
i++;
}
cout<<"揹包所能容納最大物品價值爲 "<<Vmax<<endl<<"其中包含"<<endl;
for(i=1;i<=vitop;i++)
{
j=vm[i];
cout<<"體積爲 "<<w[j]<<" 價值爲 "<<vi[j]<<" 的第 "<<j+1<<" 件物品 "<<endl;
}
system("pause");
return 0;
}