经典算法(2)——0/1背包问题(动态规划法)(ZZ)

动态规划法解决01背包问题(C++实现) 问题描述:给定n种商品和一个给定固定容量的背包。物品 i 的重量是W[ i ],价值为V[ i ],背包的容量为C。问应当如何选择装入背包中的物品,使得装入背包中的物品的总价值最大? (对于同一个物品,要么放,要么不放,不能把物品放入背包多次,也不能将物品分割后部分装入,因此该问题称为 0 - 1背包问题) #include<iostream> #include<algorithm> #include<vector> using namespace std; int t 阅读详情
           

 1. 问题描述                                   

          给定一个载重量为m,n个物品,其重量为wi,价值为vi,1<=i<=n,要求:把物品装入背包,并使包内物品价值最大                                          

2. 问题分析                              

         在0/1背包问题中,物体或者被装入背包,或者不被装入背包,只有两种选择。
                      
         循环变量i,j意义:前i个物品能够装入载重量为j的背包中
         (n+1)*(m+1)数组value意义:value[i][j]表示前i个物品能装入载重量为j的背包中物品的最大价值
         若w[i]>j,第i个物品不装入背包
         否则,若w[i]<=j且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值(替换为第i个物品装入背包后的价值)
          
          计算最大价值的动态规划算法如下:
                             
    //计算
    for(i=1;i<row;i++)
    
{
        
for(j=1;j<col;j++)
        
{
            
//w[i]>j,第i个物品不装入背包
            value[i][j]=value[i-1][j];
            
//w[i]<=j,且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值
            int temp=value[i-1][j-w[i]]+v[i];
            
if(w[i]<=j && temp>value[i][j])
                value[i][j]
=temp;
        }

    }
                       
                   
      即该段程序完成以下n个阶段:
     1:只装入1个物品,确定在各种不同载重量的背包下,能够得到的最大价值
     2:装入2个物品,确定在各种不同载重量的背包下,能够得到的最大价值
     。。。
     n:以此类推,装入n个物品,确定在各种不同载重量的背包下,能够得到的最大价值                       

3. 问题求解  

      确定装入背包的具体物品,从value[n][m]向前逆推:
           若value[n][m]>value[n-1][m],则第n个物品被装入背包,且前n-1个物品被装入载重量为m-w[n]的背包中
           否则,第n个物品没有装入背包,且前n-1个物品被装入载重量为m的背包中
      以此类推,直到确定第一个物品是否被装入背包为止。逆推代码如下:
              
    //逆推求装入的物品
    j=m;
    
for(i=row-1;i>0;i--)
    
{
        
if(value[i][j]>value[i-1][j])
        
{
            c[i]
=1;
            j
-=w[i];
        }

    }
                                                     
                          

4. 源码如下              

      输入数据及输出数据均在文件中。
      输入数据格式:
            n m
            w1 w2 ... wn
            v1 v2 ... vn
      输出数据格式:
           maxValue
           i count            //i表示物品编号,count表示该物品被选中次数
           ...
/************************************************************************
 * 0/1背包问题求解 (visual studio 2005)
 * 给定一个载重量为m,及n个物品,其重量为wi,价值为vi,1<=i<=n
 * 要求:把物品装入背包,并使包内物品价值最大
 ***********************************************************************
*/


#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>

#define FILENAMELENGTH 100

class CBeibao
{
public:
    
int m_nNumber;        //物品数量
    int m_nMaxWeight;    //最大载重量

    
int *m_pWeight;        //每个物品的重量
    int *m_pValue;        //每个物品的价值

    
int *m_pCount;        //每个物品被选中的次数
    int m_nMaxValue;    //最大价值

public:
    CBeibao(
const char *filename);
    
~CBeibao();
    
    
int GetMaxValue();
    
int GetMaxValue(int n,int m,int *w,int *v,int *c);
    
void Display(int nMaxValue);
    
void Display(int nMaxValue,const char *filename);
}
;

//读入数据
CBeibao::CBeibao(const char *filename)
{
    FILE 
*fp=fopen(filename,"r");    
    
if(fp==NULL)
    
{
        printf(
"can not open file!");
        
return;    //exit(0);
    }


    
//读入物品数量和最大载重量
    fscanf(fp,"%d%d",&m_nNumber,&m_nMaxWeight);

    m_pWeight
=new int[m_nNumber+1];
    m_pValue
=new int[m_nNumber+1];

    m_pWeight[
0]=0;
    
//读入每个物品的重量
    for(int i=1;i<=m_nNumber;i++)
        fscanf(fp,
"%d",m_pWeight+i);

    m_pValue[
0]=0;
    
//读入每个物品的价值
    for(int i=1;i<=m_nNumber;i++)
        fscanf(fp,
"%d",m_pValue+i);

    
//初始化每个物品被选中次数为0
    m_pCount=new int[m_nNumber+1];
    
for(int i=0;i<=m_nNumber;i++)
        m_pCount[i]
=0;

    fclose(fp);
}


CBeibao::
~CBeibao()
{
    delete[] m_pWeight;
    m_pWeight
=NULL;
    delete[] m_pValue;
    m_pValue
=NULL;
    delete[] m_pCount;
    m_pCount
=NULL;
}


/************************************************************************
 * 动态规划求出满足最大载重量的最大价值
 * 参数说明:n:物品个数
 *           m:背包载重量
 *           w:重量数组
 *           v:价值数组
 *           c:是否被选中数组
 * 返回值:最大价值
 ***********************************************************************
*/

int CBeibao::GetMaxValue(int n,int m,int *w,int *v,int *c)
{
    
int row=n+1;
    
int col=m+1;

    
int i,j;    //循环变量:前i个物品能够装入载重量为j的背包中

    
//value[i][j]表示前i个物品能装入载重量为j的背包中物品的最大价值
    int **value=new int*[row];
    
for(i=0;i<row;i++)
        value[i]
=new int[col];

    
//初始化第0行
    for(j=0;j<col;j++)
        value[
0][j]=0;

    
//初始化第0列
    for(i=0;i<row;i++)
        value[i][
0]=0;

    
//计算
    for(i=1;i<row;i++)
    
{
        
for(j=1;j<col;j++)
        
{
            
//w[i]>j,第i个物品不装入背包
            value[i][j]=value[i-1][j];
            
//w[i]<=j,且第i个物品装入背包后的价值>value[i-1][j],则记录当前最大价值
            int temp=value[i-1][j-w[i]]+v[i];
            
if(w[i]<=j && temp>value[i][j])
                value[i][j]
=temp;
        }

    }


    
//逆推求装入的物品
    j=m;
    
for(i=row-1;i>0;i--)
    
{
        
if(value[i][j]>value[i-1][j])
        
{
            c[i]
=1;
            j
-=w[i];
        }

    }


    
//记录最大价值
    int nMaxVlaue=value[row-1][col-1];

    
//释放该二维数组
    for(i=0;i<row;i++)
    
{
        delete [col]value[i];
        value[i]
=NULL;
    }

    delete[] value;
    value
=NULL;

    
return nMaxVlaue;
}


int CBeibao::GetMaxValue()
{
    
int nValue=GetMaxValue(m_nNumber,m_nMaxWeight,m_pWeight,m_pValue,m_pCount);
    m_nMaxValue
=nValue;
    
return nValue;
}


//显示结果
void CBeibao::Display(int nMaxValue)
{
    printf(
"   %d ",nMaxValue);
    
for(int i=1;i<=m_nNumber;i++)
    
{
        
if(m_pCount[i])
            printf(
"  %d  %d ",i,m_pCount[i]);
    }

    printf(
" ");
}


void CBeibao::Display(int nMaxValue,const char *filename)
{
    FILE 
*fp=fopen(filename,"w");    
    
if(fp==NULL)
    
{
        printf(
"can not write file!");
        
return;    //exit(0);
    }


    fprintf(fp,
"%d ",nMaxValue);
    
for(int i=1;i<=m_nNumber;i++)
    
{
        
if(m_pCount[i])
            fprintf(fp,
"%d  %d ",i,m_pCount[i]);
    }

    fclose(fp);
}


//显示菜单
void show_menu()
{
    printf(
"--------------------------------------------- ");
    printf(
"input command to test the program ");
    printf(
"   i or I : input filename to test ");
    printf(
"   q or Q : quit ");
    printf(
"--------------------------------------------- ");
    printf(
"$ input command >");
}


void main()
{
    
char sinput[10];
    
char sfilename[FILENAMELENGTH];

    show_menu();

    scanf(
"%s",sinput);
    
while(stricmp(sinput,"q")!=0)
    
{
        
if(stricmp(sinput,"i")==0)
        
{
            printf(
"  please input a filename:");
            scanf(
"%s",sfilename);

            
//获取满足最大载重量的最大价值
            CBeibao beibao(sfilename);
            
int nMaxValue=beibao.GetMaxValue();
            
if(nMaxValue)
            
{
                beibao.Display(nMaxValue);
                
int nlen=strlen(sfilename);
                strcpy(sfilename
+nlen-4,"_result.txt");
                beibao.Display(nMaxValue,sfilename);
            }

            
else
                printf(
"   error! please check the input data! ");
        }


        
//输入命令
        printf("$ input command >");
        scanf(
"%s",sinput);
    }

}
                                                                         

5. 运行结果如下                             

文件中的内容如下:
1. input.txt
        4 10
        2 3 4 7
        1 3 5 9         
                   
    input_result.txt
        12
        2  1
        4  1
                             
2. input1.txt
        5 10
        2 2 6 5 4
        6 3 5 4 6
         
    input1_result.txt
        15
        1  1
        2  1
        5  1
                             
3. input2.txt
        5 15
        2 6 4 7 9
        1 6 5 9 4
         
    input2_result.txt
        16
        1  1
        2  1
        4  1
                             
4. input3.txt
        10 105
        12 16 24 7 29 32 5 43 31 1
        11 16 15 9 24 25 3 32 41 7
         
    input3_result.txt
        112
        1  1
        2  1
        4  1
        6  1
        7  1
        9  1
      10  1
                                                      
                   
Python实现0-1背包问题算法详解及源码 接着,我们通过两重循环来遍历所有状态,并利用0-1背包问题的贪心思路来更新dp数组中的值。在计算机算法中,背包问题是一类经典问题,而0-1背包问题就是其中的一种。0-1背包问题指的是有一个固定容量的背包和一些重量不同、价值不同的物品,需要在限定总重量的前提下选择装入背包的物品,使得装入背包的物品的总价值最大。动态规划算法是一种基于贪心思路,在计算过程中通过对已知的最优解推导出新的最优解的算法。首先,设背包的容量为c,物品的数目为n,w为每个物品的重量数组,v为每个物品的价值数组。 阅读详情

相关推荐

VC++实现动态规划解决0-1背包问题

本文还有配套的精品资源,点击获取 简介:0-1背包问题是一种需要在有限背包容量下,通过选择物品组合来获得最大价值的组合优化问题。本文详细介绍了使用VC++面向对象编程语言,通过动态规划方法实现0-1背包问题的过程。动态规划通过构建一个二维数组来避免重复计算,并给出了解决方案的算法实现与优化建议。 1. 0-1背包问题概述 0-1背包问题是一种典型的组合优化问题,...

weixin_42613360的博客 1048

0-1背包问题:动态规划的经典应用

背包问题是在给定一组物品和一个背包容量的情况下,如何选择物品放入背包,以使得放入背包的物品总价值最大化。0-1背包问题是背包问题的一个经典变种,其中每个物品要么完全放入背包,要么完全不放入,不能切割物品。在本文中,我们将探讨如何使用动态规划算法解决0-1背包问题,并提供Java实现示例。0-1背包问题是背包问题的一种变种,其特点是每个物品要么完全放入背包,要么完全不放入,不能切割物品。具体而言,我们有一组物品,每个物品有自己的重量和价值,以及一个背包的容量限制。

Java领域 1万+

Lattice FPGA 开发工具Diamond使用流程总结——工具使用

本文介绍了一般的Diamond开发流程,包括工程创建、文件输入、IP使用、约束、管脚分配、和布线布局等流程

weixin_41895751的博客 2万+

剪枝函数-----0-1背包问题(c++)

#include <iostream> using namespace std; #define N 100 //默认有99个物品。第一个不使用 int w[N]; //每个物品的重量 int v[N]; //每个物品的价值 int n,c; //n:一共有多少物品,c:背包的最大容量 in...

weixin_43348682的博客 2692

Pixhawk变砖自救指南:从DFU模式到固件重刷全流程(附2.4.8实测)

本文详细介绍了Pixhawk飞控变砖后的自救方法,从DFU模式进入、固件重刷到高级恢复技巧全流程。特别针对国产版本boot0引脚未引出的特殊情况提供了解决方案,帮助用户通过QGC或Mission Planner地面站工具恢复飞控功能,适用于2.4.8等常见固件版本。

weixin_29168813的博客 337

433MHz无线通信避坑指南:如何解决信号干扰和误码问题

本文深入探讨433MHz无线通信中的信号干扰和误码问题,提供从射频前端设计到协议优化的全链路解决方案。通过天线匹配、电源噪声抑制、曼彻斯特编码改进及实时频点切换等技术,显著提升通信稳定性和距离。适合智能家居和工业无线控制系统的开发者参考。

weixin_29288313的博客 417

经典算法(2)——0/1背包问题(动态规划法)

本博客(http://blog.youkuaiyun.com/livelylittlefish)贴出作者(三二一、小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!                                                0/1背包问题                                                 1. 问题描

学习,思考,记录,分享。 8万+

触摸屏蓝牙控制

使用杰理芯片通过蓝牙实现触摸屏功能,需要结合触摸屏数据采集、蓝牙数据传输以及移动端应用的实现。

m0_46145044的博客 1109

背包问题详解(01背包,完全背包,多重背包,分组背包)

有 N 件物品和一个容量是 V的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 输出最大价值。输入格式第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。输出格式输出一个整数,表示最大价值。数据范围0

走在努力路上的自己的博客 6万+

【Burp入门第三十七篇】AutoRepeater插件安装使用教程+越权实战案例

AutoRepeater 通过接收满足特定条件的请求,按照预设的基础替换规则对请求进行处理。在接收到匹配请求后,它首先应用基础替换,然后针对每个定义的替换创建请求副本并应用该替换操作,从而实现对不同参数的修改和请求的重复发送,以此来全面检测 Web 应用的授权情况。1、自动化请求重复:能自动复制、修改并重发 HTTP 请求,避免了手动重复操作的繁琐,大大提高了 Web 应用授权测试的效率。2、灵活参数替换:可灵活改变邮箱地址、账号身份、角色、URL 和 CSRF 令牌等关键参数。

等风来 2035

8.9华为OD机试真题 新系统 - 查找最佳充电策略 (Java/Py/C/C++/Js/Go)

8.9华为OD机试真题 新系统 - 查找最佳充电策略 (Java/Py/C/C++/Js/Go)

算法大师! 1166

DP:背包问题----0/1背包问题

maximize∑i1nci⋅ximaximizei1∑n​ci​⋅xi​其中,nnn表示物品的数量,cic_ici​表示物品iii的价值。∑i1nwi⋅xi≤Ci1∑n​wi​⋅xi​≤C其中,wiw_iwi​表示物品iii的重量,CCC表示背包的容量。xi∈01xi​∈01i123ni123n其中,xix_ixi。

2301_79969994的博客 2064

基于Verilog的8位CPU设计及UART扩展实现方案,包含完整的架构设计、核心代码实现和仿真验证方法

基于Verilog的8位CPU设计及UART扩展实现方案,包含完整的架构设计、核心代码实现和仿真验证方法

a_zxswer的博客 190

0-1 背包问题的 4 种解决方法&&算法策略

蛮力法 递归与分治策略 动态规划 贪心算法 回溯法 分支限界法 前言 0-1背包是一个经典的问题,而它能用不同的算法思想去解决。恰巧最近在看算法,学习算法就是学习解决问题的思路。现在将0-1背包问题与解决方法整理出来,这样不仅能区分不同的算法思想,还能加深对0-1背包问题的理解。虽然有的算法思想并不能解决这一问题,但是为了对算法策略有一个较为整体的了解,所以在这里做一下简单的介绍。 ...

Tyler_Zx的博客 6万+

软考「系统规划与管理师(第2版)」抱佛脚|案例分析预测

规划类(系统/数据/云)+ 服务过程找错改进 + 风险应急终止三大块各备一套成熟模板,术语统一按第2版新教材口径,案例分析 45 分线的希望就大很多。

软件行业技术文化交流。 72

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

大厂/软考经典算法:0-1背包问题 动态规划法

0-1背包问题 动态规划法动态规划背包问题0-1背包:问题描述:思路:例题解题思路 动态规划 动态规划与分治法类似,就是将一个大的问题不断的向下拆分成一些小的问题,知道拆分的小问题可以求出解,然后再将这些小问题的解向上合并,最终得到大问题的解决方案。 背包问题 背包问题是经典算法,主要有 0-1背包,普通背包(多重背包,完全背包) 一般来说0-1背包问题使用动态规划求解,使用贪心算法的无法获得最优解。 0-1背包: 问题描述: 一个旅行者有一个最多能装M公斤的背包,现在有N个物品,每件的重量分别是W1、W2

qq_33105531的博客 1890

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

算法设计与分析实验二:动态规划法实现TSP问题和0/1背包问题

【实验目的】 1、熟练掌握动态规划思想及教材中相关经典算法。 2、使用动态规划法编程,求解0/1背包问题和TSP问题。 TSP问题 一、实验内容: TSP问题是指旅行家要旅行n个城市,要求每个城市经历且仅经历一次然后回到出发城市,并要求所走的路程最短。 对于图G=(V,E),假设从顶点i出发,令V’=V-i,则d(i,V’)表示从顶点i出发经过V’中各个顶点一-次且仅一次,最后回到出发点i的最短路径长度,显然,初始子问题是d(k,{}),即从顶点i出发只经过顶点k回到顶点i。现在考虑原问题的一部分,d(k,

努力学习的小菜同学 2881

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

经典算法之—背包问题

一.完全背包问题 问题描述:有一个背包容量为M,一堆物品其重量表示为W={w(1),w(2),…},物品相应的价值V={v(1),v(2),…},现在要求将物品中的一部分或全部,放入背包。要求:装入物品的总价值最高;同时满足装入物品总重量不超过M;对单个物品而言,状态可为:装入背包、不装入背包、一部分装入背包。 假设装入的物品为从w(i)到w(j),则有: 对于完全背包而言,我们采用

呵呵 3312

算法之美:0-1背包问题(动态规划法,回溯法,贪心法)

1.动态规划法:求解决策过程的最优化 #include <stdio.h> #define CAPACITY 10 //背包的容量 #define N 5 //n为物品的个数 int max(int a, int b) { return a > b ? a :...

不秃头的程序猿Gabriel的博客 1816

C语言经典算法之背包问题

给定一个背包,其容量为W,以及一组n件物品,每件物品都有一个重量wi和一个价值vi。要求从这些物品中选择一部分放入背包内,使得装入背包的物品总重量不超过背包的容量,并且使所装物品的总价值最大。

weixin_56154577的博客 2685

0-1背包问题的多种解法代码(动态规划、贪心法、回溯法、分支限界法)

0-1背包问题的多种解法代码(动态规划、贪心法、回溯法、分支限界法) 一.动态规划求解0-1背包问题 /************************************************************************/ 0-1背包问题: 给定n种物品和一个背包 物品i的重量为wi,其价值为vi 背包的容量为c 应如何选择装入背包的物品,使得装入背包中的物品 的总价值最大? 注:在选择装入背包的物品时,对物品i只有两种选择, 即装入或不装入背包。不能将物品i装入多次,也 不能

WX_timi的博客 4901

动态规划之 0-1背包问题及改进

有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。在选择装入背包的物品时,对于每种物品i,只能选择装包或不装包,不能装入多次,也不能部分装入,因此成为0-1背包问题。   形式化描述为:给定n个物品,背包容量C >0,重量 第i件物品的重量w[i]>0, 价值v[i] >0 , 1≤i

八行书 1726

四种不同算法求解0-1背包问题

0-1背包问题 一、  问题描述 1  0-1背包问题 现有n种物品,对1i,价值为正整数Vi,背包能承受的最大载重量为正整数W,现要求找出这n种物品的一个子集,使得子集中物品的总重量不超过W且总价值尽量大。在选择装人背包的物品时,对每种物品i只有两种选择,即装入背包、不装入背包。不能将物品i 装人背包多次,也不能只装入部分的物品i(注意:这里对每种物品或者全取或者一点都不取,不允许只取一部

lcw_2015的博客 3万+

经典算法精讲精练之回溯法求解0-1背包问题

最近来一波基础算法吧,掌握基础原理方可行走天下。回溯法本质是用来搜索问题的解,典型地就是使用深度优先搜索,搜索路径一般沿树形结构进行,在搜索过程中,首先会判断所搜索的树结点是否包含问题的解,如果肯定不包含,则不再搜索以该结点为根的树结点,而向其祖先结点回溯;否则进入该子树,继续按深度优先策略搜索。 可能这么说不是很容易懂,咱们来的实例吧,那就是经典的0-1背包问题,...

想不出一个好的标题,就用这个吧 6918

C语言经典算法题-2

C语言经典基础算法

记录学习路上的一些拙见 1046

经典算法 - 动态规划算法及背包问题(01背包与完全背包)

动态规划 动态规划算法通常用于求解具有某种最优解的问题 基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。 与分治法不同的是,动态规划分解得到的子问题往往不是互相独立的,即上一个子问题解可能为下一个子问题的条件(通常可以将结果填入表格) 背包问题 有一个背包容量为4kg,现在有以下物品 物体 重量 价格 吉他 1 1500 音响 4 3000 电脑 3 2000 现要求装入背包的物体价值最大,且不能超重 其中: 01背包问题:物品有

key_768的博客 3505
下一篇: HDOJ1800-------字符串Hash大杂烩
LamentCoder
博客等级 码龄18年 3粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值