1. 程式人生 > >遞迴DFS揹包問題求最優解

遞迴DFS揹包問題求最優解

揹包問題大家都知道,已知揹包的最大儲存量是V,給定n個物品,求取怎樣盛放才能是揹包價值最大。

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=30;
int n,V,maxValue=0;//n表示物品數量,V表示揹包容量
//maxvalue表示最大價值
int z[maxn],j[maxn];
void DFS(int index,int sumZ,int sumJ){//sumZ sumJ表示當前質量和價值
	if(index==n){
	if(sumZ<=V&&sumJ>=maxValue)
		maxValue=sumJ;
		return;
}
	//不選區下標為index的物品
	DFS(index+1,sumZ,sumJ);
	//選區下標為index的物品
	DFS(index+1,sumZ+z[index],sumJ+j[index]);
}  
int main(){
cin>>n>>V;
for(int i=0;i<n;i++)
cin>>z[i];
for(int i=0;i<n;i++)
cin>>j[i];
DFS(0,0,0);
cout<<maxValue;
return 0;
}

輸入:
5 8
3 5 1 2 2
4 5 2 1 3
輸出:
10
分析:該程式碼的時間複雜度是n2,對於10000級別以上的數來說是不可接受的,此時我們可以室友高逼格的剪枝來優化,操作是把DFS函式中的質量和價值判斷移到DFS(index+1,sumZ+z[index],sumJ+j[index]);之前,這樣就能一定程度上減少程式碼時間複雜度


還有類似的題目是,給定n個整數,選取k個數,使k個數的和為x,如果存在多組解,則選區平方和最大的一組

程式碼未除錯成功,暫存

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n,k,x,maxpf=0;
vector<int>tem;
vector<int>ans;
void DFS(vector<int> v,int index,int nowx,int nowk,int nowpf){
if(x==nowx&&nowk==k){
	if(nowpf>maxpf){
		maxpf=nowpf;
		ans=tem;
	}
	return;
}
if(index==n||nowk>k||nowx>x) return;
tem.push_back(v[index]);
DFS(v,index+1,nowx+v[index],nowk+1,nowpf+v[index]*v[index]);
tem.pop_back();
DFS(v,index+1,nowx,nowk,nowpf);
}  
int main(){
cin>>n>>k>>x;
vector<int>v(n);
for(int i=0;i<n;i++)
cin>>v[i];
DFS(v,0,0,0,0);
for(int i=0;i<ans.size();i++)
cout<<ans[i]<<" ";
return 0; 
}

輸入:
4 2 5
1 2 3 4
輸出:
1 4