问题描述
现要将n
个重量为w[i]
,价值为v[i]
物品装到容量为c
的背包中,如何使得背包价值最大
输入描述
第1行输入背包容量c和物品数量n
第2-n+1行输入n个物品的重量与价值
输出描述
输出最大价值
DFS
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
const ll N=1e4+10;
ll w[N];//物品重量
ll cv;//背包当前价值
ll cw;//背包当前重量
ll bestv;//最大价值
ll n;//物品数量
ll c;//背包最大装载量
struct Node{//定义节点
ll w;
ll v;
double d;
}node[N];
bool cmp(Node a,Node b)//比较函数 升序
{
return a.d>=b.d;
}
int Bound(int i) //限界函数 装满背包后的价值
{
ll cleft = c-cw;//背包剩余容量
ll b = cv;//当前价值
while(i<=n&&node[i].w<=cleft)
{
b +=node[i].v;
cleft -= node[i].w;
i++;
}
if(i<=n)
{
b+=cleft/node[i].d;
}
return b;
}
void dfs(ll t)
{
if(t>n)//叶子节点
{
if(cv>bestv)
bestv=cv;
return;
}
if(c>=cw+node[t].w)//左子树 约束
{
cw+=node[t].w; //目前重量++
cv+=node[t].v;//目前价值++
dfs(t+1);//递归到子树
cv-=node[t].v;//还原
cw-=node[t].w;//还原
}
if(Bound(t+1)>bestv)//右子树
{
dfs(t+1);//递归到子树
}
}
int main()
{
freopen("in.txt","r",stdin);
scanf("%lld %lld",&c,&n);
for(int i=1;i<=n;i++)
{
scanf("%lld %lld",&node[i].w,&node[i].v);
node[i].d=node[i].v/node[i].w*1.0;
}
sort(node+1,node+1+n,cmp);
dfs(1);
printf("%lld\n",bestv);
fclose(stdin);
return 0;
}