遞迴DFS揹包問題求最優解
阿新 • • 發佈:2018-12-15
揹包問題大家都知道,已知揹包的最大儲存量是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