dfs解决背包问题
#include <iostream>
///用深搜写
using namespace std;
int weight,maxvalue=0,n;///背包中能放物品的总质量weight,最大价值maxvalue,总的物品数量
int v[30],w[30];///物品的数量和价值
void dfs(int index,int sumw,int sumv)///第index件物品,选择的总质量sumw,总价值sumv
{
if(index==n)///死胡同,对所有的物品都选择完毕
{
if(sumw<=weight&&sumv>maxvalue) ///若符合条件,则更新最大值
maxvalue=sumv;
return;///要返回停止,否则就是死循环了
}
///要写index+1,不能写index++,否则出不来
dfs(index+1,sumw+w[index],sumv+v[index]); ///岔路口1:选择这件物品
dfs(index+1,sumw,sumv); ///岔路口2:不选择,总的来说就是一个集合有多少个子集
}
int main()
{
cin>>n>>weight;
for(int i=0;i<n;i++)///从0开始
{
cin>>w[i];
}
for(int i=0;i<n;i++) cin>>v[i];///从0开始
dfs(0,0,0);
cout << maxvalue << endl;
return 0;
}
通过减枝优化后的程序,若不遇到极端情况,效率提升许多
void DFS(int index,int sumw,int sumv)///减枝,优化一下
{
if(index==n) return;
DFS(index+1,sumw,sumv);///不选择
if(sumw+w[index]<=weight)///选择的话,要先符合总质量要小于背包容量
{
if(maxvalue<sumv+v[index]) maxvalue=sumv+v[index];
DFS(index+1,sumw+w[index],sumv+v[index]);
}
}
具体的递归过程类似于下图,每次递归进入下一层都有两种分支(岔路口)
F(3){DFS(index+1,sumw+w[indes],sumv+v[index])},F(2){DFS(index+1,sumw,sumv)
代表F(4){DFS(index,sumw,sumv)}的两个岔路口
上代码
#include <bits/stdc++.h>
using namespace std;
int n,k,maxsumsqu=-1,x;///n个数中选择k个使得他们的和为x,求出平方和最大的一组数
int a[30];///集合内元素
vector<int>temp,ans;///temp存放临时最大的方案,ans存放最终方案
void dfs(int index,int nowk,int sum,int sumsqu)
{
if(nowk==k&&sum==x)///符合选择的nowk==k个数和为x
{
if(sumsqu>maxsumsqu)
{
maxsumsqu=sumsqu;
ans=temp;///更新最优方案
}
return ;
}
///处理完n个数,或者超过k个数,或者和超过x,返回
if(index==n||nowk>k||sum>x) return;
///选择index号方案
temp.push_back(a[index]);
dfs(index+1,nowk+1,sum+a[index],sumsqu+a[index]*a[index]);
///不选择index号方案
temp.pop_back();
dfs(index+1,nowk,sum,sumsqu);
}
int main()
{
cin>>n>>k>>x;
for(int i=0;i<n;i++) cin>>a[i];
dfs(0,0,0,0);
for(int i=0;i<ans.size();i++) cout<<ans[i]<<" ";
cout<<endl;
return 0;
}