zoukankan      html  css  js  c++  java
  • 「NOIP2006」「LuoguP1064」 金明的预算方案(分组背包

    题目描述

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

    主件 附件

    电脑 打印机,扫描仪

    书柜 图书

    书桌 台灯,文具

    工作椅 无

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

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

    v[j1]×w[j1]+v[j2]×w[j2]+…+v[jk]×w[jk]v_[j_1] imes w_[j_1]+v_[j_2] imes w_[j_2]+ …+v_[j_k] imes w_[j_k]v[j1]×w[j1]+v[j2]×w[j2]++v[jk]×w[jk]。

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

    输入输出格式

    输入格式:

    111行,为两个正整数,用一个空格隔开:

    NmN mNm (其中N(<32000)N(<32000)N(<32000)表示总钱数,m(<60)m(<60)m(<60)为希望购买物品的个数。) 从第222行到第m+1m+1m+1行,第jjj行给出了编号为j−1j-1j1的物品的基本数据,每行有333个非负整数

    vpqv p qvpq (其中vvv表示该物品的价格(v<10000v<10000v<10000),p表示该物品的重要度(1−51-515),qqq表示该物品是主件还是附件。如果q=0q=0q=0,表示该物品为主件,如果q>0q>0q>0,表示该物品为附件,qqq是所属主件的编号)

    输出格式:

    一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<200000<200000<200000)。

    输入输出样例

    输入样例#1: 复制
    1000 5
    800 2 0
    400 5 1
    300 5 1
    400 3 0
    500 2 0
    
    输出样例#1: 复制
    2200

    说明

    NOIP 2006 提高组 第二题

    题解

    算是分组背包的模板题了叭?

    设主件为1,附件为2,3,

    那么将{1},{1,2},{1,3},{1,2,3}视为同组内的物件,同组内至多只能选1个。

    //如果只有一个附件,组内就是{1},{1,2};如果没有附件,组内就是{1}。

    跑分组背包就行了。

    关于分组背包:

    因为和01一样只有选和不选的区别,不像完全背包可以无限选,

    所以容积也是要从大到小循环。

    然后在一组里面只能选一个,所以干脆一组一组的跑,

    在每一组里面循环容积,在容积里面再循环每件物品,就可以保证是由不含该组物品的状态转移而来了。

     1 /*
     2     qwerta
     3     P1064 金明的预算方案
     4     Accepted
     5     100
     6     代码 C++,1.19KB
     7     提交时间 2018-10-17 09:46:49
     8     耗时/内存
     9     49ms, 932KB
    10 */
    11 #include<iostream>
    12 #include<cstdio>
    13 using namespace std;
    14 struct emm{
    15     int w,v,f,lson,rson;
    16 }a[63];//w:费用 v:价值 f:父节点
    17 struct ahh{
    18     int w,v;
    19 }b[7];//分组用的
    20 int f[32003];//dp数组
    21 int main()
    22 {
    23     //freopen("a.in","r",stdin);
    24     int n,m;
    25     scanf("%d%d",&n,&m);
    26     for(int i=1;i<=m;++i)
    27     {
    28         int v,p,fa;
    29         scanf("%d%d%d",&v,&p,&fa);
    30         a[i].w=v;
    31         a[i].v=v*p;
    32         a[i].f=fa;
    33         if(fa)
    34         {
    35             if(!a[fa].lson)
    36               a[fa].lson=i;
    37             else
    38               a[fa].rson=i;
    39         }
    40     }
    41     for(int k=1;k<=m;++k)//枚举每组
    42     if(!a[k].f)//如果该件为主件(代表一个组)
    43     {
    44         int kk=0;
    45         //分组,存在b里
    46         b[++kk]=(ahh){a[k].w,a[k].v};//1
    47         if(a[k].lson)
    48         {
    49             b[++kk]=(ahh){a[k].w+a[a[k].lson].w,a[k].v+a[a[k].lson].v};//1,2
    50             if(a[k].rson)
    51             {
    52                 b[++kk]=(ahh){a[k].w+a[a[k].rson].w,a[k].v+a[a[k].rson].v};//1,3
    53                 b[++kk]=(ahh){a[k].w+a[a[k].lson].w+a[a[k].rson].w
    54                                     ,a[k].v+a[a[k].lson].v+a[a[k].rson].v};//1,2,3
    55             }
    56         }
    57         //cout<<k<<" "<<kk<<endl;
    58         for(int v=n;v;--v)//从大到小枚举容积
    59         for(int i=1;i<=kk;++i)//循环组内元素
    60         if(v-b[i].w>=0)
    61         f[v]=max(f[v],f[v-b[i].w]+b[i].v);
    62     }
    63     cout<<f[n];//输出
    64     return 0;
    65 }
  • 相关阅读:
    从小白到全栈的前端学习路径
    Vue初学者可能不知道的坑
    vue的基础使用
    15-浮动
    02-css的选择器
    深入理解JavaScript的闭包
    深入理解JavaScript的闭包,前戏— 作用域和词法作用域
    JavaScript简介
    02-HTML5新的input属性
    springboot+spring session+redis+nginx实现session共享和负载均衡
  • 原文地址:https://www.cnblogs.com/qwerta/p/9813238.html
Copyright © 2011-2022 走看看