经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
算法学习——贪心算法之可拆背包 - Stars-one
来源:cnblogs  作者:Stars-one  时间:2018/10/20 15:43:09  对本文有异议

算法描述

已知道n种物品和一个可容纳c重量的背包,第i种物品的重量为wi,价值为pi,装包的时候可以把物品拆开(即可只装每种物品的一部分),设计如何装包,使装包所得整体的价值最高?

算法思路

  1. 首先,我们要知道,n种物品以及他们对应的价值,都是由用户输入的

  2. 我们使用贪心算法,每一步取最大效益的物品放入背包之中(及单位价值为最高的物品 单位价值=pi/wi)

  3. 由以上思路,我们可以定义一个二维数组来接收用户输入的数值

    w[i][0] 代表了第i种物品的重量(即wi)

    w[i][1] 代表了第i种物品的价值(即pi)

    w[n][m] n范围为1~n m范围为0~1

    这里需要注意,数组下标是从0开始的,我们的n是从1开始的,空出了一个0,所以我们定义n应该定义为n+1 这里应该不难理解,n+1的话,下标就是0~n,我们需要1~n这n个位置

    定义为double[][] w = new double[n+1][2]

  4. 除了上面所说,我们还需一个Flag类来存放单位价值以及该单位价值对应的第i个物品(也就是下标)

  5. 我们将单位价值计算得出后作为Flag类成员变量content,以及下标作为Flag类中的成员变量flag,之后使用ArrayList存放多个Flag类

  6. 之后,将单位价值存放在一个一维数组中,使用排序,从小到大排序

  7. 得到排序之后的一维数组,依次与ArrayList中的每一个Flag类content作比较,得到其对应的下标,存入到栈中

  8. 之后,栈顶就是单位价值最大的所对应的下标,依次取出来(即实现了每次都是取到的物品都是单位价值最大的),进行相关的运算即可

算法实现

  1. Scanner scanner = new Scanner(System.in);
  2. double cost = 0;//记录当背包满的时候所达到的价值
  3. System.out.println("输入物品个数n:");
  4. int n = scanner.nextInt();
  5. System.out.println("输入背包可装容量c:");
  6. double c = scanner.nextDouble();
  7. double temp[] = new double[n+1];
  8. double w[][] = new double[n+1][2];
  9. ArrayList<Flag> list = new ArrayList<Main.Flag>();
  10. for(int i=1;i<=n;i++){
  11. System.out.println("w"+i+"重量:");
  12. w[i][0] = scanner.nextDouble();
  13. System.out.println("w"+i+"价值:");
  14. w[i][1] = scanner.nextDouble();
  15. temp[i]=w[i][1]/w[i][0];
  16. }
  17. scanner.close();
  18. Stack<Integer> stack = new Stack<Integer>();
  19. //存入到list中,保存原来的下标和内容
  20. for(int i=1;i<temp.length;i++){
  21. Flag flag = new Flag(i, temp[i]);
  22. list.add(flag);
  23. }
  24. double t = 0;
  25. Arrays.sort(temp);//使用java中自带的快速排序
  26. //将原来的下标存入进栈中,处于栈顶的是单位价值最高的该物品的下标
  27. for(int i=1;i<temp.length;i++){
  28. for(Flag flag : list){
  29. if(flag.getContent()==temp[i]){
  30. stack.push(flag.getFlag());
  31. }
  32. }
  33. }
  34. while(!stack.isEmpty()){
  35. int i =stack.pop();//出栈
  36. c = c -w[i][0];
  37. if(c<=0){
  38. c = c+w[i][0];//加回之前所减去的内容,计算百分比
  39. double a = (c/w[i][0])*100;
  40. DecimalFormat format = new DecimalFormat("##.#");
  41. System.out.println("装入"+"第"+i+"种物品的百分之"+format.format(a)+",重量为"+w[i][0]+",价值为"+w[i][1]);
  42. cost = cost+w[i][1]*(a/100);
  43. System.out.println("最大价值为"+format.format(cost));
  44. break;
  45. }else{
  46. cost = cost+w[i][1];
  47. }
  48. System.out.println("装入"+"第"+i+"种物品"+",重量为"+w[i][0]+",价值为"+w[i][1]);
  49. }
  50. }
  51. //定义了一个Flag类,存放原来的坐标以及单位价值
  52. public static class Flag{
  53. int flag;
  54. double content;
  55. public Flag(int flag,double content){
  56. this.flag = flag;
  57. this.content= content;
  58. }
  59. public int getFlag(){
  60. return this.flag;
  61. }
  62. public double getContent(){
  63. return this.content;
  64. }
  65. }

结果

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号