背包问题(贪心算法)

  贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

  贪心算法还是比较好理解的一个算法,以前我也是这样认为的,感觉贪心就是每一步都做到最优解就可以了,但是后来结合问题发现自己的理解存在着一些问题。贪心算法比较经典的题目之一就是单源最短路径问题,这个问题在一些步骤上面我想了很久,有些细节想不通。这个问题以后有机会再讲。本次讲一讲背包问题。

  背包问题就是有若干物品,每个物品有自己的价值和重量。背包有总重量。问题就是怎样将背包装的最大价值。背包问题也分很多种,贪心算法解决的是物品可以拆分的背包问题(就是物品可以分成几份装入)。这个问题用贪心还是比较好解决的。贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。此问题就是将每次的放入看成每一步,要想解决问题,就是将每一步都放入最优解。也就是说,每一次的放入都要放入最佳的选择。讲到这里,就要说一说最佳的选择,每一次的放入的最佳的选择就是每次放入的物品都是剩余的物品中价值最大且质量最小的,这里就要引入一个物品的属性,物品的权重值。物品的权重值就是指物品的价值除以物品的质量。所以,本问题的每一次的最佳选择就是每次都选出权重值最大的物品。

  问题的大致思路说完了,下面就讲一讲具体的算法。算法最开始是先声明物品类,因为后面要用到很多的物品属性,如果使用数组会有点麻烦,物品的属性有背包ID,物品价值,物品质量,物品权重值。在声明的时候,只要输入物品的前三个属性就可以了,物品的权重值可以由前三个推导出来。算法的接下来就是将物品的数组按物品的权重值排序,权重值大的排在数组的前面,方便后面的运算。算法的主体就是从数组中取出物品对象,计算比较物品的质量和当前背包剩余重量的大小,如果大于,就计算要放入的百分比。如果小于,就进行下一步的最佳选择。算法的大致思路及时这样。下面粘贴代码:

 1 package sf;
 2
 3 import java.util.Scanner;
 4
 5 public class demo6
 6 {
 7     //选择排序将数组中的bag按权重排序
 8     public static void sort(Bag[] p)
 9     {
10         Bag t;
11         for(int i=0;i<p.length;i++)
12         {
13             int max=i;
14             t=p[i];
15             for(int j=i;j<p.length;j++)
16             {
17                 if(t.wi<p[j].wi)
18                 {
19                     t=p[j];
20                     max=j;
21                 }
22             }
23             t=p[i];
24             p[i]=p[max];
25             p[max]=t;
26
27         }
28     }
29     //背包问题(贪心算法)
30     public static void bq(Bag[] p,int k,int w,double v)
31     {
32         if(p[k].weight<w)
33         {
34             v=v+p[k].value;
35             System.out.println(p[k].pid+"全部装入,当前背包价值为"+v);
36             w=w-p[k].weight;
37             bq(p, k+1, w, v);
38         }else{
39             double a=w*p[k].wi;//当前价值
40             v=v+a;
41             System.out.println(p[k].pid+"装入了"+((double)w/p[k].weight)+",当前背包价值为"+v);
42         }
43
44     }
45     public static void main(String args[])
46     {
47         System.out.println("请输入背包的容量w和物品的个数n");
48         Scanner reader = new Scanner(System.in);
49         int w=reader.nextInt();//背包的容量
50         int n=reader.nextInt();//物品的个数
51         Bag[] p=new Bag[n];
52         //10 10 a 10 10 b 10 15 c
53         System.out.println("请依次输入各个物品的重量w和价值v和名称s");
54         int weigth;
55         int value;
56         String pid;
57         for(int i=0;i<n;i++)
58         {
59             weigth=reader.nextInt();
60             value=reader.nextInt();
61             pid=reader.next();
62             p[i]=new Bag(weigth,value,pid);
63         }
64         //System.out.println(z[1]+""+v[1]);
65         sort(p);
66         bq(p,0,w,0.0);
67         for(int i=0;i<n;i++)
68         {
69             System.out.println(p[i].wi+" "+p[i].pid);
70         }
71
72     }
73
74 }
75
76 class Bag
77 {
78     public int weight;//重量
79     public int value;//价值
80     public double wi;//权重
81     public String pid;//背包名称
82     public  Bag(int w,int v,String pid)
83     {
84         this.weight=w;
85         this.value=v;
86         this.pid=pid;
87         this.wi=(double)value/weight;
88     }
89 }

  具体实现的问题大部分都在注释中了,虽然也没有多少注释,还是讲讲吧。在控制台输入的时候,要注意物品是先声明,在使用对象属性。最开始一直报错,想了很久,都是用数组用习惯了,直接就使用数组元素了。排序算法用的是选择,因为选择排序对于元素较少的情况下计算效果还是比较理想的。贪心算法的主体用的是递归。算法的实现还是比较简单的。主要是理解贪心算法的思想,做出每一步都是最优解的选择。

原文地址:https://www.cnblogs.com/yanyu01/p/8977921.html

时间: 2024-11-03 01:37:16

背包问题(贪心算法)的相关文章

分数背包问题(贪心算法)

#include<iostream> #include<iterator> #include<vector> #include<algorithm> using namespace std; /* *分数背包问题(贪心算法) */ struct goods { double value;//物品的价值 double weight;//物品的重量 double ratio;//物品的性价比 double in;//物品装入背包的重量 int index;//物

NYOJ~106~背包问题~贪心算法~

背包问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w<=10):如果给你一个背包它能容纳的重量为m(10<=m<=20),你所要做的就是把物品装到背包里,使背包里的物品的价值总和最大. 输入 第一行输入一个正整数n(1<=n<=5),表示有n组测试数据: 随后有n测试数据,每组测试数据的第一行有两个正整数s,m(1<=s<=10

JAVA算法基础-贪心算法

前言 学无止境.算法博大精深啊,一个贪心算法里面就隐含了这么多不同的场景实现,每个场景下的算法就有多种不同的实现,个人写法不一也成就了各种不同的漂亮算法,看了这些实现,也让我开拓了思维,这个世界的方案永远没有最完美的只有最合适的- ! 1.贪心算法概念 贪心算法也叫贪婪算法,当然叫法随意.主要目的是在问题求解时,做出最正确的判断= =,这不是贪心是啥?在计算机工程领域当中,就是说不考虑整体最优算法而是从局部做到最优解.当然贪心是算法不能对所有的问题都能得到整体都最优解,但对多数个问题还是能得到近

野生前端的数据结构练习(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;

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

贪心策略.关于贪心算法的思考,思考过程都放在代码中了. package com.lip.datastructure; /** *贪心算法:装箱问题的思考 * @author Lip *装箱问题可以是时间调问题的延伸,当一个箱子没有容积限制,那么就是时间调度问题 *在时间调度问题中:存在两个可以讨论的问题.1.平均最短时间 2.总的最短时间 *这两个问题都和装箱问题中问题如此类似. */ /* * 上面是我理解的装箱问题,本来是想说背包问题的 * 背包问题的描述:有N件物品和一个容量为V的背包.第

[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行按照输入物品的顺序