精华内容
下载资源
问答
  • C语言递归方法求解背包问题C语言递归方法求解背包问题,编译环境vs2019上问题:上代码: C语言递归方法求解背包问题,编译环境vs2019 上问题: 十、背包问题求解 假设有一个能装入总体积为T的背包和n件体积分别为...

    C语言递归方法求解背包问题,编译环境vs2019

    上问题:

    十、背包问题的求解
    假设有一个能装入总体积为T的背包和n件体积分别为w1 , w2 , … , wn 的物品,能否从n件物品中挑选若干件恰好装满背包,即使w1 +w2 + … + wn=T,要求找出所有满足上述条件的解。例如:当T=10,各件物品的体积{1,8,4,3,5,2}时,可找到下列4组解:
    (1,4,3,2)
    (1,4,5)
    (8,2)
    (3,5,2)。

    上代码:

    #include<stdio.h>
    int answer[100] = { 0 };//保存结果
    int p = 0;//answer的指针
    void bag(int *nums, int locate, int total, int len, int big) {
    	for (int i = locate; i < len; i++) {
    		total += answer[p++] = nums[i];//total取和,answer保存当前的数
    		if (total < big) {//比背包小的时候进入递归
    			bag(nums, i + 1, total, len, big);
    			total -= answer[--p];//递归结束减去当前数,准备进入下一次循环
    		}
    		else if (total > big)//比背包大
    			total -= answer[--p];
    		else if (total == big) {//和背包相等打印结果
    			for (int j = 0; j < p; j++)
    				printf("%d ", answer[j]);
    			printf("\n");
    			total -= answer[--p];
    		}
    	}
    }
    void main() {
    	int nums[] = { 1,8,4,3,5,2 }, big = 10, total = 0, len = sizeof(nums)/sizeof(int), locate = 0;
    	bag(nums, locate, total, len, big);
    }
    
    展开全文
  • 0-1背包问题 已知背包的容量为b,有n种物件,其价格依次为w1,w2,...,wn;其容量依次为v1,v2,...,vn。 现要求在背包允许的容量内,装的物件价值达到最大,其数字模型为: max z=1 x1 + 6 x2 + 18 x3 + 22 x4 + 28 ...
  • 贪心算法求解背包问题 #include<stdio.h> #define maxnumber 20 typedef struct node { float w; float v; int i; }Object; float find(Object wp[],int n,float M) { float x[maxnumber]; int i; float maxprice=0;...
  • 背包问题之贪婪算法求解C语言源代码).背包问题之贪婪算法求解C语言源代码).
  • 通过贪心算法和结构体,用价值率求解小数背包问题


    问题描述:

    给定 𝑛 种物品和一个背包。物品 𝑖 的重量是𝑊𝑖,其价值为𝑉𝑖,背包的容量为C,应如何选择装入背包的物品使得装入背包中物品的总价值最大?
    这里,在选择物品𝑖装入背包时,可以选择物品𝑖的一部分,而不一定要全部装入背包。


    思路及分析:

    首先能够想到有三种装物品的方法:

    一:在不超出当前背包的剩余容量前提下,优先选择价值最大的物品,这样使得装入价值增长最快。
    二:在不超出当前背包的剩余容量前提下,优先选择重量最轻的物品,这样使得背包容量增长最慢。
    三:在不超出当前背包的剩余容量前提下,优先选择价值率(价值除以重量)最大的物品,这样使得背包中单位重量价值增长最快。

    但是第一,二种方法有时却得不到最优解,所以在这里,主要说明第三种方法:

    价值率: 可以直接理解为单位重量的物品值多少钱

    结合题干可以看出,每一件物品都有各自的属性和价值率,所以,在算法的实现过程中,需要用到结构体来规范属性及对应物品。

    struct Object  //定义了一个名为 Object 的结构体
    {
    	int value;  //物品的价值
    	int weight;  //物品的重量
    	double rate;  //物品的价值率
    }Obj[MAX];  //定义了一个结构体数组
    

    算法介绍及使用:

    贪心算法:(百度百科)

    贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
    贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

    根据贪心算法的解释,我们可以设计出贪心算法的设计思路:
    如下:

    1. 预处理 把物品按照价值率进行降序排列。
      既然要对价值率进行降序排列,自然少不了排序算法:(任意排序算法都可以)
    void sort(Object A[])
    {
        int i,j;
        for (i = 0 ; i < n - 1 ; i++)
        {
    		int a = i; 
    		for (j = i + 1; j < n; j++) 
    			if (A[j].rate > A[a].rate)
    				{
    					a = j; 
    			    }
    		Object temp=A[a];
    		A[a]=A[i];
    		A[i]=temp;
    	}
    }
    
    1. 选择第一个物品 根据贪心策略,首先选择价值率最大的物品,并记录该物品装入的重量。
      排好序后,先选择价值率最大的物品放入:代码如下
    if(A[i].weight<=c)
    		{
    			E+=A[i].value;  //保存最大价值
    			D+=A[i].weight; //保存最大重量
    			c-=A[i].weight; //更新背包剩余重量
    		}
    
    1. 贪心选择后续步骤 依次扫描每一个物品,在没有超出背包容量的条件下,尽可能多地装入当前价值率最高的物品,并记录该物品装入的重量。(注:题干已经说明:在选择物品 𝑖 装入背包时,可以选择物品 𝑖 的一部分,而不一定要全部装入背包。)
      而当 if 语句中的条件不成立时,就应该只装入物品 i 的一部分:
    else
    	{
    		int demo=(A[i].value/A[i].weight*1.0)*c;  
    		//定义一个临时变量,用来保存背包最后剩余部分能装多少价值的物品。
    		E+=demo;   //更新背包能够装下的最大价值
    		D+=demo*A[i].weight/A[i].value*1.0;
    		/*   最大重量的更新思路:
    		   		  价值		重量
    		假如	   a		 b
    		已知      demo		 ?
    			则 ?= demo * b / a
    		*/
    		break;  //背包已装满,跳出循环
    	}
    

    对于背包问题,在得到最优解时,背包可能仍有剩余空间。


    完整代码及运行结果示例:

    完整代码:

    #include <stdio.h>
    
    #define MAX 1000
    
    int n,c;
    struct Object
    {
    	int value;
    	int weight;
    	double rate;
    }Obj[MAX];
    
    void sort(Object A[]);
    void load(Object A[]);
    
    void main()
    {
    	printf("请输入物品总数(0~1000)和背包的容量(0~1000):\n");
    	scanf("%d%d",&n,&c);
    	printf("请分别输入物品的价值和重量:\n");
    	for(int i=0;i<n;i++)
    	{
    		scanf("%d%d",&Obj[i].value,&Obj[i].weight);
    		Obj[i].rate=Obj[i].value/(Obj[i].weight*1.0);
    	}
    	sort(Obj);
    	load(Obj);
    }
    
    
    void sort(Object A[])
    {
        int i,j;
        for (i = 0 ; i < n - 1 ; i++)
        {
    		int a = i; 
    		for (j = i + 1; j < n; j++) 
    			if (A[j].rate > A[a].rate)
    				{
    					a = j; 
    			    }
    		Object temp=A[a];
    		A[a]=A[i];
    		A[i]=temp;
    	}
    }
    
    void load(Object A[])
    {
    	int D=0,E=0; //D 为最大重量, E 为最大价值
    	for(int i=0;i<n;i++)
    	{
    		if(A[i].weight<=c)
    		{
    			E+=A[i].value;  //保存最大价值
    			D+=A[i].weight; //保存最大重量
    			c-=A[i].weight; //更新背包剩余重量
    		}
    		else
    		{
    			int demo=(A[i].value/A[i].weight*1.0)*c;
    			E+=demo;
    			D+=demo*A[i].weight/A[i].value*1.0;
    			break;  //背包已装满,跳出循环
    		}
    	}
    	printf("背包最多能够装下的物品最大价值为:%d,最大重量为:%d",E,D);
    }
    

    运行结果示例:

    请输入物品总数(0~1000)和背包的容量(0~1000)3 50
    请分别输入物品的价值和重量:
    60 10
    100 20
    120 30
    背包最多能够装下的物品最大价值为:240,最大重量为:50
    
    展开全文
  • 完全版分支界限法求解背包问题,易于理解 分支界限法0-1背包问题
  • 动态规划法求解0/1背包问题 C语言

    千次阅读 多人点赞 2018-07-01 14:12:55
    0/1背包问题是给定n个重量为{w1, w2, … ,wn}、价值为{v1, v2, … ,vn}的物品和一个容量为C的背包,求这些物品中的一个最有价值的子集,并且要能够装到背包中。  在0/1背包问题中,物品i或者被装入背包,或者...

        0/1背包问题是给定n个重量为{w1, w2, … ,wn}、价值为{v1, v2, … ,vn}的物品和一个容量为C的背包,求这些物品中的一个最有价值的子集,并且要能够装到背包中。

        在0/1背包问题中,物品i或者被装入背包,或者不被装入背包,设xi表示物品i装入背包的情况,则当xi=0时,表示物品i没有被装入背包,xi=1时,表示物品i被装入背包。0/1背包问题可以看作是决策一个序列(x1, x2, …, xn),对任一变量xi的决策是决定xi=1还是xi=0。在对xi-1决策后,已确定了(x1, …, xi-1),在决策xi时,问题处于下列两种状态之一:(1)背包容量不足以装入物品i,则xi=0,背包不增加价值;(2)背包容量可以装入物品i,则xi=1,背包的价值增加了vi。 这两种情况下背包价值的最大者应该是对xi决策后的背包价值。

    基本思路:

     

        0/1背包问题,首先判断当前背包容量是否可以容纳该物品,如果背包重量超过当前背包容量就不可以放入,如果小于则需要进一步判断,假设当前物品为i,重量为wj,则取前i-1个物品装入容量为j的背包的价值和前i-1个物品装入容量为j-wj的背包加上物品i的价值的最大值。

        按照这样的思路,填写过程表格,背包最大价值就是过程矩阵最后一个元素的值。最后倒推求出是哪些物品。

     

    程序清单:

     

    #include<stdio.h>
    
    /*结构体 物品*/
    struct Goods
    {
    	int id;				//物品编号
    	int is_in_bag;		        //当前物品是否在背包中,1表示在背包,0表示不在
    	int weight;			//当前物品的重量
    	int value;			//当前物品的价值
    }goods[50];                             //目前所支持最大物品数量为50,可根据实际情况调整
    
    
    /*函数原型声明*/
    int KnapSack(struct Goods goods[50] ,int n,int C);	//求背包的最大价值
    void PrintInfo(struct Goods goods[50],int n);		//输出物品信息
    void IsInBagInfo(struct Goods goods[50],int n);		//装入背包中的物品的信息
    
    
    /*主函数*/
    int main()
    {
    	int i;
    	int capacity;		//背包的容量
    	int goods_number;	//物品的个数
    	int max_value;		//最大价值
        /*输入背包容量、物品个数、物品重量、物品价值*/
    	printf("请输入背包容量:");
    	while(scanf("%d",&capacity) != EOF)
    	{	
            printf("请输入物品的个数:");
    		scanf("%d",&goods_number);
    		while(goods_number > 50)
    		{
    			printf("抱歉,当前所容许最大物品数量为50,请您重新输入");
    			scanf("%d",&goods_number);
    		}
            printf("请输入%d物品的重量:",goods_number);
    		for(i=0;i<goods_number;i++)
    		{
    			goods[i].id=i+1;
    			goods[i].is_in_bag=0;//默认表示当前物品不在背包
    			scanf("%d",&goods[i].weight);
    		}
    		printf("请输入%d个物品的价值:",goods_number);
    		for(i=0;i<goods_number;i++)
    		{
                scanf("%d",&goods[i].value);
    		}
    		/*输出用户输入的信息*/
    		PrintInfo(goods,goods_number);
    		/*求最大价值*/
    		max_value=KnapSack(goods,goods_number,capacity);
    	    /*输入背包中物品的信息*/
    	    IsInBagInfo(goods,goods_number);
    		/*输出最大价值*/
    		printf("\n最大价值为%d",max_value);
    		/*开始下一次计算*/
    		printf("\n\n\n请输入背包容量");
    	}
    	return 0;
    }
    
    /*输出物品信息*/
    void PrintInfo(struct Goods goods[50],int n)
    {
    	int i=0;
        printf("--------------------------------------------------------\n");
    	printf("您输入的物品信息如下:\n");
       	printf("\n物品ID\t重量\t价值\n");
    		for(i=0;i<n;i++)
    		{
    			printf("%d\t%d\t%d\n",goods[i].id,goods[i].weight,goods[i].value);
    		}
    }
    
    
    
    /*求背包的最大价值*/
    // n——n个物品
    // C——背包容量为C
    int KnapSack(struct Goods goods[50] ,int n,int C)
    {
    	int i,j;
    	int V[50][50]={0};	//存放迭代结果
    	//初始化第0列
    	for(i=0;i<=n;i++)	
    	{
    		V[i][0]=0;
    	}
    	//初始化第0行
    	for(j=0;j<=C;j++)	
    	{
    		V[0][j]=0;
    	}
    	//分别计算每一行
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<=C;j++)
    		{
    			if(j<goods[i-1].weight) //物品重量大于背包重量,不能放入
    				V[i][j]=V[i-1][j];
    			else					//物品重量小于等于背包重量
    			{
                    V[i][j]=(V[i-1][j]>V[i-1][j-goods[i-1].weight]+goods[i-1].value)?V[i-1][j]:V[i-1][j-goods[i-1].weight]+goods[i-1].value;
    			}
    		}
    	}
    	//求装入背包的物品
        for(j=C,i=n;i>0;i--)
    	{
             if(V[i][j]>V[i-1][j])
    		 {
    			 goods[i-1].is_in_bag=1;
    			 j=j-goods[i-1].weight;
    		 }
    		 else
    		 {
    			 goods[i-1].is_in_bag=0;
    		 }
    	}
    	//输出计算过程
    	printf("--------------------------------------------------------\n");
    	printf("计算过程如下:\n");
    	for(i=0;i<=n;i++)
    	{
    		for(j=0;j<=C;j++)
    			printf("%3d",V[i][j]);
    		printf("\n");
    	}
    	//返回背包最大价值
    	return V[n][C];
    }
    
    
    /*输出装入背包中的物品的信息*/
    void IsInBagInfo(struct Goods goods[50],int n)
    {
    	int i=0;
    	printf("--------------------------------------------------------\n");
    	printf("背包中的物品为:\n");
    	printf("物品ID\t重量\t价值\n");
    	for(i=0;i<n;i++)
    		{
    			if(goods[i].is_in_bag==1)
    				printf("%d\t%d\t%d\n",goods[i].id,goods[i].weight,goods[i].value);
    		}
    }

    参考结果:

     

    展开全文
  • 例如,对于有n种可选择物品的0-1背包问题,其解空间由长度为n的0-1向量组成。该解空间包含对变量的所有可能的0-1赋值。当n=3时,其解空间是{(0,0,0),(0,0,1),(0,1,0),(0,1,1),(1,0,0),(1...

    回溯法求解01背包

      用回溯法解问题时,应明确定义问题的解空间。问题的解空间至少应包含问题的一个(最优)解。例如,对于有n种可选择物品的0-1背包问题,其解空间由长度为n的0-1向量组成。该解空间包含对变量的所有可能的0-1赋值。当n=3时,其解空间是{(0,0,0),(0,0,1),(0,1,0),(0,1,1),(1,0,0),(1,0,1),(1,1,0),(1,1,1)} 定义了问题的解空间后,还应将解空间很好的组织起来,使得能用回溯法方便地搜索整个解空间。通常将解空间组织成树或图的形式。

      例如,对于n=3时的0-1背包问题,可用一棵完全二叉树表示其解空间,如图5-1所示。

      解空间树的第i层到第i+1层表上的标号给出了变量的值。从树根到叶的任一路径表示解空间中的一个元素。例如,从根节点到节点H的路径相应于解空间中的元素(1,1,1)。

      确定了解空间的组织结构后,回溯法送开始节点(根节点)出发,以深度优先方式搜索整个解空间。这个考试节点成为活结点,同时也成为当前的扩展节点。在当前的扩展结点处,搜索向纵深方向移至一个新节点。这个新节点就成为新的活结点,并成为当前扩展节点,如果在当前的扩展节点处不能退再向纵深方向移动,则当前扩展节点就成为死节点。此时,应往回移动至最近的一个活结点处,并使这个活结点成为当前的扩展节点。回溯法以这种工作方式递归的在解空间中搜索,直至找到所要求的结果解空间中已无活结点为止。

      例如,对于n=3时的0-1背包问题,考虑下面的具体实例:w=【16,15,15】,p=【45,25,25】,c=30。从图5-1的根节点开始搜索其解空间。开始时,根节点时唯一的活结点,也是当前的扩展节点。在这个扩展节点处,可以沿纵深方向移至节点B或者节点C。假设选择先移至节点B。此时,节点A和节点B时活结点,节点B成为当前扩展节点。由于选取了w1,股灾节点B处剩余背包容量是r=14,获得的价值为45.从节点B处,可以移至节点D处或E。由于移至节点D至少需要w2=15的背包容量,而现在仅有的背包容量是r=14,故移至节点D导致不可行解。搜索至节点E不需要背包容量,因而是可行的。从而选择移至节点E。此时,E成为新的扩展节点,节点A,B和E是活结点。在节点E处,r=14,获取的价值为45.从节点E处,可以向纵深移至节点J或节点K。移至节点J导致不可行解,而移向节点K是可行的,于是移向节点K,它成为新的扩展节点。由于节点K是叶节点,故可得到一个可行解。这个解相应的价值为45。xi的取值由根节点到叶节点K的路径唯一确定,即x=(1,0,0)。由于在节点K处已不能再向纵深扩展,所以节点K成为死节点。在返回到节点E处。此时在节点E处也没有可扩展的节点,它也成为死节点。

      接下来又返回到节点B处。节点B同样也成为死节点,从而节点A再次成为当前扩展节点。节点A还可继续扩展,从而到达节点C。此时,r=30,获取的价值为0。从节点C可移向节点F或节点G。假设移至节点F,它成为新的扩展节点。节点A,C,F是活结点。在节点F处,r=15,获取的价值为25。从节点F向纵深移至节点L处,此时r=0,获取的价值为50.由于L是叶节点,而且是迄今为止找到的获取价值最高的可行解,因此记录这个可行解。节点L不可扩展,我们返回到节点F处。按此方式继续搜索,可搜索遍整个解空间。搜索结束后找到的最好解释相应0-1背包问题的最优解。

                    

    #include<stdio.h>
    #define max 100
    
    int weight[max];
    int value[max];
    int n,max_weight,max_value;
    
    int best_answer[max],answer[max];
    
    void print()
    {
    	int i,j,k,l;
    	printf("+++++++++++++%d++++++++++++\n",max_value);
    	
    	for(i=1;i<=n;i++)
    		printf("%d ",best_answer[i]);
    	printf("\n");
    }
    
    void DFS(int level,int current_weight,int current_value)
    {
    	if(level>=n+1)
    	{
    		if(current_value>max_value)
    		{
    			int i;
    			max_value = current_value;
    			for(i=1;i<=n;i++)
    				best_answer[i] = answer[i];
    		}
    	}
    	else
    	{
    		if(current_weight>=weight[level+1])
    		{
    			current_weight = current_weight - weight[level+1];
    			current_value = current_value + value[level+1];
    			answer[level+1] = 1;
    			DFS(level+1,current_weight,current_value);
    			answer[level+1] = 0;
    			current_weight = current_weight + weight[level+1];
    			current_value = current_value - value[level+1];
    		}
    		DFS(level+1,current_weight,current_value);
    	}
    }
    
    void init()
    {
    	int i,j,k,l;
    	max_value = 0;
    	for(i=1;i<=n;i++)
    		answer[i] = 0;
    }
    
    int main()
    {
    	int i,j,k,l;
    	while(scanf("%d%d",&n,&max_weight)!=EOF)
    	{
    		for(i=1;i<=n;i++)
    			scanf("%d",&weight[i]);
    		for(j=1;j<=n;j++)
    			scanf("%d",&value[j]);
    		
    		init();
    		
    		DFS(0,max_weight,0);
    		
    		print();
    			
    		
    	}
    	return 0;
    	
    }
    
    /*
     3 30
     16 15 15
     45 25 25
     5 10
     2 2 6 5 4
     6 3 5 4 6 
     
     
    */
    

     

     

    展开全文
  • 完全背包问题 c语言

    2021-01-31 11:38:14
    求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 输出最大价值。 输入格式 第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。 接下来有 N 行,每行两个整数 vi,wi,用...
  • C语言-多重背包问题

    2014-05-21 23:56:00
    多重背包问题 问题:有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 分析: 这题目和...
  • 针对0/1背包问题编写了简洁的C语言代码进行求解,注释详细,通俗易懂
  • c语言-01背包问题

    2014-05-20 23:53:00
    01背包问题 问题:有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。 分析: 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。 ...
  • c语言-完全背包问题

    2014-05-20 23:57:00
    完全背包问题 问题:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 分析: 这个...
  • 遗传算法的01背包问题(c语言) 遗传算法的01背包问题(c语言) 遗传算法的01背包问题(c语言) 基于遗传算法的0-1背包问题求解 摘要 一前言 组合优化问题的求解方法研究已经成为了当前众多科学关注的焦点这不仅在于其...
  • 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 输出最大价值。 输入格式 第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。 接下来有 N 行,每行两个整数 vi,wi,用...
  • 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。 输入格式 第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。 接下来有 N 行,每行两个整数 vi,wi,用...
  • c语言实现的基于动态规划求解01背包问题,,其中2.txt中的内容为: 4 5 2 1 3 2 12 10 20 15
  • 基于遗传算法的0-1背包问题求解,(c语言描述)
  • 求解将哪些物品装入背包可使价值总和最大。 动态规划  我们定义一个二维数组,其中每个元素代表一个状态,即前i个物体中放入体积为j背包中最大价值。  其中,dp[0][j]=0,dp[i][0]=0(因为无论体积为0,还是没有物品...
  • 动态规划算法,背包问题的好算法.利用动态规划设计的背包问题求解过程和实现过程,如有不足,请各位兄弟朋友帮帮忙改改。

空空如也

空空如也

1 2 3 4 5
收藏数 90
精华内容 36
关键字:

c语言背包问题求解

c语言 订阅