zoukankan      html  css  js  c++  java
  • [洛谷P1064] 金明的预算方案

    洛谷题目链接:金明的预算方案

    题目描述

    金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过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]。(其中为乘号)

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

    输入输出格式

    输入格式:

    输入的第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)。

    输入输出样例

    输入样例#1:

    1000 5
    800 2 0
    400 5 1
    300 5 1
    400 3 0
    500 2 0

    输出样例#1:

    2200

    说明

    NOIP 2006 提高组 第二题

    一句话题意: 给出(n)个物品,选用附件必须先选用主件,选用一个物品(i)得到的价值是(i)的花费乘以(i)的重要度.问在范围内能得到最大的价值是多少.

    题解: 考虑到每个主件都最多只有2个附件,所以可以考虑用01背包的方法枚举主件,那么转移状态的时候就有这几种情况:

    • 只选主件
    • 选一个主件的同时选一个附件
    • 选一个主件的同时选另外一个附件
    • 选一个主件的同时选两个主件
    • 不选

    可以定义状态(f[j])表示(j)元钱能得到的最大价值.用(t1,t2)表示两个附件,(i)表示主件,那么我们可以改一下状态转移方程:

    [f[j] = max(f[j],f[j-cost_{i}]+val_i,f[j-cost_{i,t1}]+val_{i,t1},f[j-cost_{i,t2}]+val_{i,t2},f[j-cost_{i,t1,t2}]+val_{i,t1,t2} ]

    然后注意一下处理主件附件关系就没什么问题了.

    #include<bits/stdc++.h>
    using namespace std;
    const int N=60+5;
    
    int money, n, ans = 0, f[32005], vis[N][3];
    
    struct thing{
        int cost, imp, bel;
    }a[N];
    
    int v(int x){
        return a[x].cost;
    }
    
    int val(int x){
        return a[x].cost*a[x].imp;
    }
    
    int main(){
        //freopen("data.in","r",stdin);
        cin >> money >> n;
        for(int i=1;i<=n;i++)
    	cin >> a[i].cost >> a[i].imp >> a[i].bel;
        memset(f, 128, sizeof(f)); f[0] = 0;
        for(int i=1;i<=n;i++)
    		if(a[i].bel) vis[a[i].bel][++vis[a[i].bel][0]] = i;
        for(int i=1;i<=n;i++)
    		if(a[i].bel == 0)
    		    for(int j=money;j>=a[i].cost;j--){
    				f[j] = max(f[j], f[j-a[i].cost]+a[i].imp*a[i].cost);
    				int t1 = vis[i][1], t2 = vis[i][2];
    				if(t1 && j >= v(i) + v(t1))
    				    f[j] = max(f[j], f[j-v(i)-v(t1)] + val(i) + val(t1));
    				if(t2 && j >= v(i) + v(t2))
    				    f[j] = max(f[j], f[j-v(i)-v(t2)] + val(i) + val(t2));
    				if(t1 && t2 && j >= v(i) + v(t1) + v(t2))
    				    f[j] = max(f[j], f[j-v(i)-v(t1)-v(t2)] + val(i) + val(t1) + val(t2));
    				ans = max(ans, f[j]);
    		    }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    瓜子二手车直卖网面试经历
    189. Rotate Array
    183. Customers Who Never Order
    182. Duplicate Emails
    文本的样式
    字体font
    定位position
    float引起的高度塌陷问题
    盒子大小 轮廓阴影 圆角
    文档流 颜色单位
  • 原文地址:https://www.cnblogs.com/BCOI/p/9041993.html
Copyright © 2011-2022 走看看