博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Sicily 1346. 金明的预算方案
阅读量:6200 次
发布时间:2019-06-21

本文共 3961 字,大约阅读时间需要 13 分钟。

 

【原题】
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 5800 2 0400 5 1300 5 1400 3 0500 2 01000 5800 2 0400 5 1300 5 1400 3 0500 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
7 #include
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 else34 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<
<

转载于:https://www.cnblogs.com/mrlaker/archive/2012/07/17/2595345.html

你可能感兴趣的文章
视频、续航与超级计算,APU革新CPU的三把斧
查看>>
利用mysql-cluster软件实现mysql集群
查看>>
DOM编程
查看>>
linux系统在虚拟机上不能使用桥接模式
查看>>
详解 Android 的 Activity 组件
查看>>
Ubuntu下安装Python的Tkinter和Pmw库
查看>>
Nhibernate中One—to—One关系映射详解
查看>>
JavaScript正则表达式19例(17)
查看>>
F5意想不到的问题
查看>>
直接编辑Excel 单元格,而不需双击才能输入
查看>>
Linux中openssl用法(搭建CA服务器)
查看>>
Docker容器快速入门
查看>>
Windows Phone 实用开发技巧(17):自定义应用程序的Tile
查看>>
服务器硬件监控之OMSA
查看>>
mysql 使用mysqldump 备份和还原
查看>>
Awt和Swing的对比
查看>>
Android第二十三期 - 256k的ListView下拉刷新和滚动加载数据
查看>>
Windows server 2003 ADMT
查看>>
Android 使用httpclient对self-signed certificate网站进行SSL连线
查看>>
Android第三十期 - 标题联动ViewPage+Fragment
查看>>