zoukankan      html  css  js  c++  java
  • 有依赖的背包问题-购物单

    题目:
    王强今天很开心,公司发给N元的年终奖。王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
     
    主件 附件
    电脑 打印机,扫描仪
    书柜 图书
    书桌 台灯,文具
    工作椅
    如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。王强想买的东西很多,为了不超出预算,他把每件物品规定了一个重要度,分为 5 等:用整数 1 5 表示,第 5 等最重要。他还从因特网上查到了每件物品的价格(都是 10 元的整数倍)。他希望在不超过 N 元(可以等于 N 元)的前提下,使每件物品的价格与重要度的乘积的总和最大。
        设第 j 件物品的价格为 v[j] ,重要度为 w[j] ,共选中了 k 件物品,编号依次为 j 1 , j 2 ,……, j k ,则所求的总和为:
    v[j 1 ]*w[j 1 ]+v[j 2 ]*w[j 2 ]+ … +v[j k ]*w[j k ] 。(其中 * 为乘号)
        请你帮助王强设计一个满足要求的购物单。
    输入:

    输入的第 1 行,为两个正整数,用一个空格隔开:N m

    (其中 N ( <32000 )表示总钱数, m ( <60 )为希望购买物品的个数。)
    从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v p q
    (其中 v 表示该物品的价格( v<10000 ), p 表示该物品的重要度( 1 5 ), q 表示该物品是主件还是附件。如果 q=0 ,表示该物品为主件,如果 q>0 ,表示该物品为附件, q 是所属主件的编号)
    输出:
    输出文件只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值( <200000 )。
    示例:
    1000 5 800 2 0 400 5 1 300 5 1 400 3 0 500 2 0
    2200
     
    思路:该题包含主件和附件,那么总的形式有主件,主件+附件1,主件+附件2,主件+附件1+附件2,将其转换成背包问题。
     
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Scanner;
    public class Main {
        public static void main(String[] args) {
            Scanner scanner=new Scanner(System.in);
            int sum=scanner.nextInt();
            int N=scanner.nextInt();
            List<Item> extraItems=new ArrayList<Main.Item>();
            Map<Integer, Group> groupMap=new HashMap<Integer, Main.Group>();
            for(int i=0;i<N;i++)
            {
                int price=scanner.nextInt();
                int deg=scanner.nextInt();
                int q=scanner.nextInt();
                Item item=new Item();
                item.price=price;
                item.value=price*deg;
                item.id=(q==0?i+1:q);
                if(q==0)//主件
                {
                    Group group=new Group();
                    group.item=item;
                    groupMap.put(item.id, group);
                }
                else 
                {
                    if(groupMap.get(q)!=null)
                    {
                        Group group=groupMap.get(q);
                        if(group.accessory!=null)
                        {
                            group.accessory.add(item);
                        }
                        else 
                        {
                            group.accessory=new ArrayList<Main.Item>();
                            group.accessory.add(item);
                        }
                    }
                    else 
                    {
                        extraItems.add(item);
                    }
                }
            }
            //将顺序有误的加入
            for(int i=0;i<extraItems.size();i++)
            {
                Item item=extraItems.get(i);
                int id=item.id;
                if(groupMap.get(id)!=null)
                {
                    Group group=groupMap.get(id);
                    if(group.accessory!=null)
                    {
                        group.accessory.add(item);
                    }
                    else 
                    {
                        group.accessory=new ArrayList<Main.Item>();
                        group.accessory.add(item);
                    }
                }
            }
            //将有依赖的百宝问题转换成背包问题
            List<Item> bag=new ArrayList<Main.Item>();
            Iterator<Map.Entry<Integer, Group>> iterator=groupMap.entrySet().iterator();
            while(iterator.hasNext())
            {
                Entry<Integer,Group> entry=iterator.next();
                int id=entry.getKey();
                Group group=entry.getValue();
                if(group.accessory==null)
                {
                    bag.add(group.item);
                }
                else if(group.accessory.size()==1)
                {
                    Item acItem=group.accessory.get(0);
                    Item item=group.item;
                    bag.add(item);
                    Item newItem=new Item();
                    newItem.price=item.price+acItem.price;
                    newItem.value=item.value+acItem.value;
                    bag.add(newItem);
                }
                else if(group.accessory.size()==2)
                {
                    Item ac1=group.accessory.get(0);
                    Item ac2=group.accessory.get(1);
                    Item item =group.item;
                    bag.add(item);
                    Item n1=new Item();
                    n1.price=item.price+ac1.price;
                    n1.value=item.value+ac1.value;
                    Item n2=new Item();
                    n2.price=item.price+ac2.price;
                    n2.value=item.value+ac2.value;
                    Item n3=new Item();
                    n3.price=item.price+ac2.price+ac1.price;
                    n3.value=item.value+ac2.value+ac1.value;
                    bag.add(n1);
                    bag.add(n2);
                    bag.add(n3);
                }
            }
            //对背包进行规划
            System.out.println(getMax(bag, bag.size(), sum));
            scanner.close();
        }
        
        public static int getMax(List<Item> list,Integer index,int extraMoney)
        {
            if(index==0 || extraMoney==0) return 0;
            if(list.get(index-1).price>extraMoney)//if money is not enough
            {
                return getMax(list, index-1, extraMoney);
            }
            else 
            {
                int m1=getMax(list, index-1, extraMoney);
                int m2=getMax(list, index-1, extraMoney-list.get(index-1).price)+list.get(index-1).value;
                return Math.max(m1, m2);
            }
        }
        
        static class Item
        {
            int id;
            int price;
            int value;//价格与重要度的乘积
        }
        static class Group
        {
            Item item;
            List<Item> accessory;
        }
    }
  • 相关阅读:
    基于live555实现的RTSPServer对底层进行性能优化的方法
    基于live555实现的RTSPServer对底层进行性能优化的方法
    EasyPlayerPro(Windows)流媒体播放器开发之框架讲解
    EasyPlayerPro(Windows)流媒体播放器开发之框架讲解
    EasyPlayerPro(Windows)流媒体播放器开发之跨语言调用
    EasyPlayerPro(Windows)流媒体播放器开发之跨语言调用
    EasyPlayerPro(Windows)流媒体播放器开发之接口设计
    EasyPlayerPro(Windows)流媒体播放器开发之接口设计
    EasyPlayerPro(Windows)流媒体播放器开发之ffmpeg log输出报错
    EasyPlayerPro(Windows)流媒体播放器开发之ffmpeg log输出报错
  • 原文地址:https://www.cnblogs.com/maydow/p/4818557.html
Copyright © 2011-2022 走看看