ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

背包问题的分支界限算法

2019-10-26 22:53:18  阅读:287  来源: 互联网

标签:node 背包 int 重量 nod 算法 界限 物品


背包问题,分支界限算法

注释和思路都在代码里了。。

递归+剪枝优化

分支界限,就是根据条件来剪枝,条件边界就叫做界,求是否满足条件的过程就叫作代价函数

不能直接copy代码的

代码

#include<bits/stdc++.h>
using namespace std;

int n; //物品数量 
int limitWeight; //背包上限重量 
const int maxn = 1010;
int bestValue = 0; //最优值 背包能装的最大价值 

//物品node 两个属性 价值 和 重量 
struct node{
    int v;
    int w;
};

//定义排序规则 
bool cmp(node a,node b){
    double flag1 = a.v*1.0/a.w;
    double flag2 = b.v*1.0/b.w;
    return flag1 > flag2; //按价值与重量比排序 
}

struct node nod[maxn];//存放物品的结构体数组 
int takeNum[maxn]; //记录拿物品的数量 
int bestTake[maxn]; //记录最优的 拿物品的数量 

//第x个物品时 当前背包的重量 code by:fishers 
void dfs(int x,int curWeight,int curValue){
    
    if(x == n+1){ //递归出口 拿第x+1个物品了 就是到达了叶节点 
        if(curValue > bestValue && curWeight <= limitWeight){
            bestValue = curValue; //更新最优值 
            for(int i=1;i<=n;i++) bestTake[i] = takeNum[i];
        }
        return; //结束递归 
    }
    
    int nextMaxValue = curValue + (limitWeight - curWeight)*(nod[x].v/nod[x].w); //分支界限: 以后最大也就是用背包剩下的重量全拿这个物品x(因为之前按重量价值比排序啦,小贪心) 
    if(nextMaxValue < bestValue) return; //和最优值(已经搜索出的背包最大价值)比较(剪枝优化),小于最优值就直接返回了  
    
    int curMaxNum = (limitWeight - curWeight)/nod[x].w; //当前一层最多拿物品x的个数 (以确保不超过最大背包重量上限limitWeight) 
    for(int i=curMaxNum;i>=0;i--){ //枚举每一个分支 i表示拿这个物品的个数:拿i个 
        int nextWeight = curWeight + i * nod[x].w; //如果这一次拿了i个物品 算出nextWeight重量 上一轮重量+这一轮i个物品x的重量 
        if(nextWeight > limitWeight) continue;
        int nextActualValue = curValue + i * nod[x].v; //拿了i个物品后实际的价值 
        takeNum[x] = i; //记录第x个物品 拿的个数i 
        dfs(x+1,nextWeight,nextActualValue); //递归搜索下一个 物品的情况 
        takeNum[x] = 0;
    }
}

void input(){
    cin>>n>>limitWeight; //输入物品个数n,背包承受的重量上限 
    for(int i=1;i<=n;i++) cin>>nod[i].v; //输入每个物品的价值 
    for(int i=1;i<=n;i++) cin>>nod[i].w; //输入每个物品的重量 
    sort(nod+1,nod+n+1,cmp); //把物品按 价值重量比 排序 (贪心,也是后面分支界限来剪枝的前提) 
}

int main(){
    input();
    
    dfs(1,0,0);
    
    cout<<"背包最多装的价值是"<<bestValue<<endl;
    for(int i=1;i<=n;i++) {
        cout<<"拿了"<<bestTake[i]<<"个"<<"重量为"<<nod[i].w<<",价值为"<<nod[i].v<<"的物品."<<endl;
    }
    return 0;
} 

/*
4 10
1 3 5 9
2 3 4 7
*/

运行结果是这个样子

不能直接copy

标签:node,背包,int,重量,nod,算法,界限,物品
来源: https://www.cnblogs.com/fisherss/p/11746121.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有