数据结构之贪心算法(背包问题的思考)-(十)

贪心策略。关于贪心算法的思考,思考过程都放在代码中了。

package com.lip.datastructure;
/**
 *贪心算法:装箱问题的思考
 * @author Lip
 *装箱问题可以是时间调问题的延伸,当一个箱子没有容积限制,那么就是时间调度问题
 *在时间调度问题中:存在两个可以讨论的问题。1.平均最短时间 2.总的最短时间
 *这两个问题都和装箱问题中问题如此类似。
 */
/*
 * 上面是我理解的装箱问题,本来是想说背包问题的
 * 背包问题的描述:有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。
 * 求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
 */
/*
 * 贪心算法可以解决装箱问题,也可以解决背包问题,但是由贪心算法求出的解的可能不是最优解。
 * 如:事实上,作为一个理性人,我们都是贪心的。当你面对一堆金银珠宝的时候,你有一个背包,你的选择肯定会是优先选择性价比最高的珠宝。
 * 那么,从这个角度来说,我们可以用贪心算法来解决背包问题,即使不是问题的最优解。但是,这个解却是一个理人人的通常选择的贪心 策略。
 */
public class Pack
	{

		public static void main(String[] args)
			{
				/***********************装箱问题********************************/
				int []weight={8,7,5,4,4,3,3,2,2,2,1};
				int []box={12,12,12,10};
				int []result=loadInBox(Type.OFFLINE, box, weight);

				for(int i=0;i<box.length;i++)
					{
						System.out.println("第"+(i+1)+"号箱子货物:");
						print(weight, result, i+1);
						System.out.println();
					}
//				/***********0-1背包问题**************/
//				int []weight={2,3,4,6,2,5,4,3,8,1};
//				int []value={7,8,13,20,17,9,12,15,5,5};
//				int c=20;
//				int []position=loadInPack(c, value, weight);
//				int sum=0;
//				int sumW=0;
//				for(int i=0;i<position.length;i++)
//					{
//						if(position[i]!=0)
//							{
//							  sumW+=weight[position[i]-1];
//							  sum+=value[position[i]-1];
//							  System.out.println(position[i]+"->("+weight[position[i]-1]+","+value[position[i]-1]+")");
//							}
//						else break;
//					}
//				System.out.println("最大的收益为:"+sum);
//				System.out.println("有多少空间没有利用:"+(c-sumW));

			}
		/***********************装箱问题********************************/
		/**
		 * @param type
		 * @param box 箱子
		 * @param weight 货物重量
		 * @return
		 */
		public static int[]loadInBox(Type type,int box[],int []weight)
		{
			int []result=new int[weight.length];
			Sort.quickSort(weight);
			int sum=0;
			for(int i=0;i<weight.length;i++)
				sum+=weight[i];
			int sum2=0;//箱子总容积
			for(int i=0;i<box.length;i++)
				sum2+=box[i];
			if(sum>sum2)//艹,箱子不够
				return null;
			if(type==Type.OFFLINE)//给每个箱子都分配一个最大的货物
				{
					for(int i=weight.length-1,j=0;i>-1;i--)
						{
							int find=box.length;
							while(weight[i]>box[j])//不可以装
								{
									j=(j+1)%box.length;
									find--;
									if(find==0)//箱子不够
										{
										System.out.println("------背包不够---------");
										  return null;
										}
								}
							result[i]=j+1;
							box[j]-=weight[i];
							j=(j+1)%box.length;
						}
				}
			else if(type==Type.ONLINE)//先装一个箱子
				{
				   for(int i=0;i<box.length;i++)
					   {
						  //box[i] 箱子的当前剩余,也就是还可以装的货物
						   for(int j=weight.length-1;j>-1;j--)//一直装,直到装满
							  {
								  if(box[i]==0)//该箱子装满了
									  break;
								  if(result[j]==0&&weight[j]<=box[i])//该货物没有被装
									  {
										  box[i]-=weight[j];
										  result[j]=i+1;
									  }
							  }
					   }
			    }
			return result;
		}
		public static void print(int []weight,int []result,int k)
		{
			for(int i=0;i<result.length;i++)
				if(result[i]==k)
					System.out.print(weight[i]+" ");
		}
		/**
		 *
		 * @author Lip
		 * 解决装箱问题有两种方式,一种是联机,一种是脱机。
		 * 所谓联机就是将一个箱子完全放满货物后,再开始处理下一个箱子
		 * 脱机就是将所有的货物都读取进来,按照从大到小的顺序将货物分配给箱子,直到各个箱子都被装满
		 */
		public enum Type
		{
			ONLINE,OFFLINE;
		};
		/**************************0-1背包问题(贪心算法)************************************/
		/**
		 *
		 * @param c 背包容量
		 * @param value 每个物品的价值
		 * @param weight 每个物品的容积
		 */
		/*
		 * 当使用贪心算法解决背包问题时,那么考虑到贪心策略,就是要保证当前选择是最好的。
		 * 那么另外一个参考量“性价比”就被引用,p=value/weight
		 * 一直选择性价比最高的物品放入到背包中,直至背包被放满
		 */
        public static int[] loadInPack(int c,int[]value,int []weight)
        {

        	double []price=new double[value.length];//性价比
        	int []position=new int[value.length];
        	int p=0;
        	for(int i=0;i<value.length;i++)
        		price[i]=(double)value[i]/weight[i];
        	//开始装了
        	while(c>0)
        		{
        			double max=-1;
        			int pos=-1;
        			for(int i=0;i<price.length;i++)//找性价比最高的,且没有被装到背包中的
        				{
        					if(price[i]!=-1&&price[i]!=0&&max<price[i])
        						{
        							max=price[i];
        							pos=i;
        						}
        				}
        			if(pos==-1)//虽然剩下空间,但是再也找不到合适的了
        				break;
        			if(c>=weight[pos])
        				{
        					c-=weight[pos];
        					price[pos]=-1;//已经装过
        					position[p]=pos+1;
        					p++;
        				}
        			else
        				{
        					price[pos]=0;//装不下,但是可以装比这个更小的
        				}
        		}

        	return position;

        }
	}

贪婪算法运行效果:

脱机装箱:

联机装箱:

贪心算法解决0-1背包问题:

在下篇中用动态规划法解决0-1背包问题

时间: 2024-12-24 09:11:21

数据结构之贪心算法(背包问题的思考)-(十)的相关文章

十:贪心算法-背包问题

问题:贪心算法-背包问题题目描述有一背包空间为m,现有n个物体,他们的重量为w[i],价值为v[i].应该如何选择装入背包的物品,使其装入背包的物品总价值最大?(因为采用贪心算法,最终的结果不一定最优,但应该是接近于最优.提示:本题所选的方法为每次选取单位价值最高的物品)输入第一行分别为背包的空间m和物品数量n接下来有n行每行分别为物体的w[i]和价值v[i]输出一个整数样例输入30 328 3012 2014 20样例输出 40 1 #include<stdio.h> 2 int k=0;

数据结构与算法学习之路:背包问题的贪心算法和动态规划算法

一.背包问题描述: 有N种物品和一个重量为M的背包,第i种物品的重量是w[i],价值是p[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包重量,且价值总和最大. 二.解决方法: 1.贪心算法:贪心算法基于的思想是每一次选择都作当前最好的选择,这样最后的结果虽然不一定是最优解,但是也不会比最优解差很多. 举个例子说明可能好懂一些:一帮基友去聚餐,菜是一份一份上的,我每一次夹菜都只夹牛肉/海鲜吃,可能到最后我吃的牛肉/海鲜很多,但不一定代表我吃掉的东西的总价值最高,但是相对来说价值也很高

背包问题:动态规划和贪心算法

1. 动态规划 以下关于动态规划的文字描述来源 动态规划之背包问题(一) 作者:Hawstein 出处:http://hawstein.com/posts/dp-knapsack.html 一切都要从一则故事说起. 话说有一哥们去森林里玩发现了一堆宝石,他数了数,一共有n个. 但他身上能装宝石的就只有一个背包,背包的容量为C.这哥们把n个宝石排成一排并编上号: 0,1,2,-,n-1.第i个宝石对应的体积和价值分别为V[i]和W[i] .排好后这哥们开始思考: 背包总共也就只能装下体积为C的东西

算法导论笔记——第十六章 贪心算法

通常用于最优化问题,我们做出一组选择来达到最优解.每步都追求局部最优.对很多问题都能求得最优解,而且速度比动态规划方法快得多. 16.1 活动选择问题 按结束时间排序,然后选择兼容活动. 定理16.1 考虑任意非空子问题Sk,令am是Sk中结束时间最早的活动,则am在Sk的某个最大兼容活动子集中. 16.2 贪心算法原理 设计贪心算法步骤: 1>将最优化问题转化为这样的形式:对其做出一次选择后,只剩下一个子问题需要求解. 2>证明作出贪心选择后,原问题总是存在最优解,即贪心选择总是安全的. 3

野生前端的数据结构练习(12)贪心算法

参考代码可见:https://github.com/dashnowords/blogs/tree/master/Structure/GreedyAlogrithm 一.贪心算法 贪心算法属于比较简单的算法,它总是会选择当下最优解,而不去考虑单次递归时是否会对未来造成影响,也就是说不考虑得到的解是否是全局最优.在很多实际问题中,寻找全局最优解的代价是非常大的,这时候就可以通过求次优解来解决问题,这种思想其实在软件工程中很常见,例如React中著名的DOM Diff算法中需要对比两棵DOM树,树的完

贪心算法之背包问题

贪婪算法的基本思想:通过一系列步骤来构造问题的解,每一步都是对已构造的部分解的一个扩展,直到获得问题的完整解. 贪婪算法中,每一步“贪婪地” 选择最好的部分解,但不顾及这样选择对整体的影响(局部最优),因此得到的全局解不一定最好的解,但对许多问题它能产生整体最优解. 具体算法描述: public static void Greedy()        {            float cu = c;            int temp = 0;            int i = 0;

[C++] 贪心算法之活动安排、背包问题

一.贪心算法的基本思想 在求解过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解. 从贪心算法的定义可以看出,贪心算法不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解.如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一. 二.贪心算法的基本要素 (1)最优子结构性质 (2)贪心选择性质(局部最优选择) 三.贪心算法实例 1.活动安排 设有n个活

背包问题:0/1背包问题 普通背包问题(贪心算法只适用于普通背包问题)

//sj和vj分别为第j项物品的体积和价值,W是总体积限制. //V[i,j]表示从前i项{u1,u2,…,un}中取出来的装入体积为j的背包的物品的最大价值. 第一种:0/1背包问题 最大化 ,受限于  1)若i=0或j=0,  V[i,j] = 0 2)若j<si, V[i,j] = V[i-1,j] 3)若i>0且j>=si, V[i,j] = Max{V[i-1,j],V[i-1,j-si]+vi} 第二种:背包问题:在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部

贪心算法练习题:部分背包问题

/*----------------------------------------------------- 有n个物体,第i个物体的重量是wi,价值为vi, 选若干个物体,使得在总重量不超过c的情况下让总价值尽量高. 这里每个物体都可以只取走一部分,价值和重量按比例计算. 输入: 第一行输入两个整数表示n和c. 第2到第n+1行每行两个整数分别表示wi和vi. 输出: 第一行输出所选物品的总价值v和总重量w以及所选物品的种类数num.两两之间用空格分隔. 第二行到第n+1行按照输入物品的顺序