背包問題的分支界限算法


背包問題,分支界限算法

注釋和思路都在代碼里了。。

這里的背包問題,就是完全背包,可以無限次拿同一種物品的那種

遞歸+剪枝優化

分支界限,就是根據條件來剪枝,條件邊界就叫做界,求是否滿足條件的過程就叫作代價函數

代碼

#include<bits/stdc++.h>
using namespace std;

int n; //物品數量 
int limitWeight; //背包上限重量 
const int maxn = 1010;
int bestValue = 0; //最優值 背包能裝的最大價值 

//物品node 兩個屬性 價值 和 重量 
struct node{
	int v;
	int w;
};

//定義排序規則 
bool cmp(node a,node b){
	double flag1 = a.v*1.0/a.w;
	double flag2 = b.v*1.0/b.w;
	return flag1 > flag2; //按價值與重量比排序 
}

struct node nod[maxn];//存放物品的結構體數組 
int takeNum[maxn]; //記錄拿物品的數量 
int bestTake[maxn]; //記錄最優的 拿物品的數量 

//第x個物品時 當前背包的重量 code by:fishers 
void dfs(int x,int curWeight,int curValue){
	
	if(x == n+1){ //遞歸出口 拿第x+1個物品了 就是到達了葉節點 
		if(curValue > bestValue && curWeight <= limitWeight){
			bestValue = curValue; //更新最優值 
			for(int i=1;i<=n;i++) bestTake[i] = takeNum[i];
		}
		return; //結束遞歸 
	}
	
	int nextMaxValue = curValue + (limitWeight - curWeight)*(nod[x].v/nod[x].w); //分支界限: 以后最大也就是用背包剩下的重量全拿這個物品x(因為之前按重量價值比排序啦,小貪心) 
	if(nextMaxValue < bestValue) return; //和最優值(已經搜索出的背包最大價值)比較(剪枝優化),小於最優值就直接返回了  
	
	int curMaxNum = (limitWeight - curWeight)/nod[x].w; //當前一層最多拿物品x的個數 (以確保不超過最大背包重量上限limitWeight) 
	for(int i=curMaxNum;i>=0;i--){ //枚舉每一個分支 i表示拿這個物品的個數:拿i個 
		int nextWeight = curWeight + i * nod[x].w; //如果這一次拿了i個物品 算出nextWeight重量 上一輪重量+這一輪i個物品x的重量 
		if(nextWeight > limitWeight) continue;
		int nextActualValue = curValue + i * nod[x].v; //拿了i個物品后實際的價值 
		takeNum[x] = i; //記錄第x個物品 拿的個數i 
		dfs(x+1,nextWeight,nextActualValue); //遞歸搜索下一個 物品的情況 
		takeNum[x] = 0;
	}
}

void input(){
	cin>>n>>limitWeight; //輸入物品個數n,背包承受的重量上限 
	for(int i=1;i<=n;i++) cin>>nod[i].v; //輸入每個物品的價值 
	for(int i=1;i<=n;i++) cin>>nod[i].w; //輸入每個物品的重量 
	sort(nod+1,nod+n+1,cmp); //把物品按 價值重量比 排序 (貪心,也是后面分支界限來剪枝的前提) 
}

int main(){
	input();
	
	dfs(1,0,0);
	
	cout<<"背包最多裝的價值是"<<bestValue<<endl;
	for(int i=1;i<=n;i++) {
		cout<<"拿了"<<bestTake[i]<<"個"<<"重量為"<<nod[i].w<<",價值為"<<nod[i].v<<"的物品."<<endl;
	}
	return 0;
} 

/*
4 10
1 3 5 9
2 3 4 7
*/

運行結果是這個樣子


免責聲明!

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



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