码迷,mamicode.com
首页 > 其他好文 > 详细

有依赖的背包问题-购物单

时间:2015-09-18 11:32:52      阅读:295      评论:0      收藏:0      [点我收藏+]

标签:

题目:
王强今天很开心,公司发给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;
    }
}

 

有依赖的背包问题-购物单

标签:

原文地址:http://www.cnblogs.com/maydow/p/4818557.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!