DFS/BFS

一  DFS深度优先遍历

有n件物品,每件物品重量为w[i],价值位c[i]。现在需要选出若干件物品放入一个容量为V的背包中,使得在选入背包中的物品容量和不超过容量V的前提下,让背包中物品的价格之和最大,求最大价值。

由于对每件物品都有选与不选两种选择,这就是岔道口。一旦选择的物品重量之和超过V,就会到达死胡同,需要返回就近的岔道口。

显然每次都要对物品进行选择,因此DFS函数的参数必须记录当前处理的物品编号index,还需要记录在处理当前物品之前,已选物品的总重量sumW和总价值sumC

void DFS(int index,int sumW,int sumC)

如果选择不放入index号物品,那么sumW和sumC就不变,接下来处理index+1号物品,选择的分支如下

void DFS(index+1,sumW,sumC)

如果选择放入index号物品,那么sumW和sumC将分别加w[index]和c[index],接下来处理index+1号物品,选择的分支如下

void DFS(index+1,sumW+w[index],sumC+c[index])

一旦index涨到了n,说明已经把n件物品处理完毕(物品的编号位为0到n-1),此时记录的就是所选物品的总重量和总价值。如果sumW不超过V而且sumC大于一个全局的记录最大总价值的变量maxValue,说明当前的选择方案可以得到最大的价值,于是用sumC代替maxValue

#include <iostream>
#include <cstdio>

using namespace std;

const int maxn=10;
int n,V,maxValue=0;  //n件物品,背包容量为V,最大价值maxValue
int w[maxn],c[maxn];  //分别为每件物品的重量和价值

void DFS(int index,int sumW,int sumC)
{
    if(index==n)  //进入死胡同,已经处理完所有物品
    {
        if(sumW<=V&&sumC>maxValue)
        {
            maxValue=sumC;
        }
        return;
    }
    //岔道口
    DFS(index+1,sumW,sumC);   //不选index件物品
    DFS(index+1,sumW+w[index],sumC+c[index]);  //选择第index件物品
}

int main()
{
    scanf("%d%d",&n,&V);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&w[i]);   //每件物品重量
        scanf("%d",&c[i]);   //每件物品的价值
    }
    DFS(0,0,0);
    printf("%d\n",maxValue);
    return 0;
}

由于每件物品都有2中选择,因此代码时间复杂度为O(2n)(2的n次幂)。但其实仔细分析就会发现,在进入岔道口之前可以先来判断下是否满足背包容量不超过V这个特点,如果已经不满足,就不必进入岔道口了。

void DFS(int index,int sumW,int sumC)
{
    if(index==n)  //进入死胡同,已经处理完所有物品
    {
        return;
    }
    //岔道口
    DFS(index+1,sumW,sumC);   //不选index件物品
    //只有在选择加入第indecx个物品时才判断是否超出容量
    if(sumW+w[index]<=V)
    {
        if(sumC+c[index]>maxValue)
        {
            maxValue=sumC+c[index];   //更新最大价值
        }
        DFS(index+1,sumW+w[index],sumC+c[index]);  //选择第index件物品
    }

}

记录选择的物品编号

#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

const int maxn=10;
int n,V,maxValue=0;  //n件物品,背包容量为V,最大价值maxValue
int w[maxn],c[maxn];  //分别为每件物品的重量和价值
vector<int> temp,ans;

void DFS(int index,int sumW,int sumC)
{
    if(index==n)  //进入死胡同,已经处理完所有物品
    {
        return;
    }
    //岔道口
    //只有在选择加入第indecx个物品时才判断是否超出容量
    if(sumW+w[index]<=V)
    {
        if(sumC+c[index]>maxValue)
        {
            maxValue=sumC+c[index];   //更新最大价值
            ans=temp;
        }
        temp.push_back(index);
        DFS(index+1,sumW+w[index],sumC+c[index]);  //选择第index件物品
        temp.pop_back();
        DFS(index+1,sumW,sumC);   //不
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值