Sicily 1346. 金明的预算方案

 

【原题】
Time Limit: 1sec    Memory Limit:32MB
Description

金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:

 

 

 

主件

 

 

 

附件

 

 

 

电脑

 

 

 

打印机,扫描仪

 

 

 

书柜

 

 

 

图书

 

 

 

书桌

 

 

 

台灯,文具

 

 

 

工作椅

 

 

 

 

 

 

如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有0个、1个或2个附件。附件不再有从属于自己的附件。金明想买的东西很多,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用整数1~5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是10元的整数倍)。他希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。

 设第j件物品的价格为v[j],重要度为w[j],共选中了k件物品,编号依次为j1,j2,……,jk,则所求的总和为:

 v[j1]*w[j1]+v[j2]*w[j2]+ …+v[jk]*w[jk]。(其中*为乘号)

 请你帮助金明设计一个满足要求的购物单。

 

Input

输入包含多个测试数据。

每个测试数据的第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是所属主件的编号)

 

Output
对于每个测试数据,输出一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<200000)。
Sample Input
 Copy sample input to clipboard
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
Sample Output
2200 2200


【思路】
有依赖的背包问题,我的代码只是针对附件个数为2的情况,不具扩展性,更一般的情况应该是可以处理附件个数比较多的情况,不过看了别人的代码理解不了,看来还没到那个level。就先用这种过了再说吧。

我的解法是,既然附件个数不会超过两个,那么只有4种情况:主件、主件+附件1、主件+附件2、主件+附件1+附件2,把这四种情况都求出来,就变成分组背包问题,即每个组里面有4个物品(如果该主件没有附件或只有一个附件,那么这四种情况中有些不存在就记为0),然后就用分组背包的处理方法求解。
 1 // Problem#: 1346
 2 // Submission#: 1457193
 3 // The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
 4 // URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
 5 // All Copyright reserved by Informatic Lab of Sun Yat-sen University
 6 #include<iostream>
 7 #include<memory.h> 
 8 using namespace std;
 9 int main()
10 {
11     int n,m;
12     while(cin>>n>>m)
13     {
14             int vv[61],pp[61],qq[61];
15             memset(vv,0,sizeof(vv));
16             memset(pp,0,sizeof(pp));
17             memset(qq,0,sizeof(qq));                    
18 
19             
20             int p[61][4],v[61][4];
21             int a[61][2];         //一个主件最多有两个附件,没有的话就记为0     
22             memset(v,0,sizeof(v));
23             memset(p,0,sizeof(p));                   
24             memset(a,0,sizeof(a));
25             
26             for(int i=1;i<=m;i++)
27             {
28                cin>>vv[i]>>pp[i]>>qq[i];
29                if(qq[i])             //标记附件 
30                {
31                         if(!a[qq[i]][0])
32                         a[qq[i]][0] = i;
33                         else
34                         a[qq[i]][1] = i;
35                }
36             }
37             int f[61][4];     //存放每种情况的价值v*p; 
38             memset(f,0,sizeof(0));
39             for(int i=1;i<=m;i++)     //变成分组背包 
40             {
41                 if(!qq[i])
42                 {
43                   f[i][0] = vv[i] * pp[i];
44                   f[i][1] = vv[ a[i][0] ]*pp[ a[i][0] ] + vv[i] * pp[i];
45                   f[i][2] = vv[ a[i][1] ]*pp[ a[i][1] ] + vv[i] * pp[i];
46                   f[i][3] = vv[ a[i][0] ]*pp[ a[i][0] ] + vv[ a[i][1] ]*pp[ a[i][1] ] + vv[i] * pp[i];
47         
48                   v[i][0] = vv[i];                                 
49                   v[i][1] = vv[ a[i][0] ] + vv[i];                                   
50                   v[i][2] = vv[ a[i][1] ] + vv[i];                                  
51                   v[i][3] = vv[ a[i][0] ] + vv[ a[i][1] ] + vv[i];                                   
52                 }
53             }
54 
55             
56             int dp[n+1];
57             memset(dp,0,sizeof(dp));
58             for(int i=1;i<=m;i++)       //分组背包 
59             {
60               if(!qq[i])
61                   for(int j=n;j>=0;j--)                     
62                      for(int k=0;k<4;k++)
63                      {
64                              if(j-v[i][k]>=0)
65                              dp[j]=max(dp[j],dp[j-v[i][k]] + f[i][k]);
66                      }
67             }
68             cout<<dp[n]<<endl;
69     }
70     return 0; 
71 }                                 
posted @ 2012-07-17 15:51  mrlaker  阅读(651)  评论(0编辑  收藏  举报