蓝桥杯 ADV-164 算法提高 金明的预算方案

算法提高 金明的预算方案

时间限制:1.0s   内存限制:256.0MB

问题描述

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

主件 附件
电脑 打印机,扫描仪
书柜 图书
书桌 台灯,文具
工作椅


  如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有0个、1个或2个附件。附件不再有从属于自己的附件。金明想买的东西很多,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为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]。(其中*为乘号)
  请你帮助金明设计一个满足要求的购物单。

输入格式

  输入文件budget.in 的第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是所属主件的编号)

输出格式

  输出文件budget.out只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<200000)。

样例输入

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

样例输出

2200

分析:设共有n个主件,分别记作m_1, m_2, \cdots, m_n,其中主件m_i的价格为v_i,重要度为p_i。并且每个主件可以有0/1/2个附件,记主件m_i的附件为m_{i, 0}m_{i, 1}(若有的话),它们相应的价格为v_{i, 0}v_{i,1},重要度为p_{i, 0}p_{i,1}

f(i, V)为在剩余钱数为V的前提下、选取第1~i件主件及其附件所能得到的最大价格与重要度乘积之和。则根据主件有的附件数进行分类讨论:

1. 若主件m_i没有附件,则递推关系式为

f(i, V) = \max \begin{Bmatrix} f(i-1, V) \\ f(i-1, V-v_i) + v_i p_i \end{Bmatrix}

其中第1个式子表示不买主件m_i,第2个式子表示买主件m_i

2. 若主件m_i有1个附件,则递推关系式为

f(i, V) = \max \begin{Bmatrix} f(i-1, V) \\ f(i-1, V-v_i) + v_i p_i \\ f(i-1, V-v_i-v_{i,0}) + v_i p_i + v_{i, 0} p_{i, 0} \end{Bmatrix}

其中第1个式子表示不买主件m_i,第2个式子表示只买主件m_i而不买任何附件,第3个式子表示买主件m_i并且还买附件m_{i, 0}

3. 若主件m_i有2个附件,则递推关系式为

f(i, V) = \max \begin{Bmatrix} f(i-1, V) \\ f(i-1, V-v_i) + v_i p_i \\ f(i-1, V-v_i-v_{i,0}) + v_i p_i + v_{i, 0} p_{i, 0} \\ f(i-1, V-v_i-v_{i,1}) + v_i p_i + v_{i, 1} p_{i, 1} \\ f(i-1, V-v_i-v_{i,0}-v_{i,1}) + v_i p_i + v_{i, 0} p_{i, 0} + v_{i, 1} p_{i, 1} \end{Bmatrix}

其中第1个式子表示不买主件m_i,第2个式子表示只买主件m_i而不买任何附件,第3个式子表示买主件m_i并且还买附件m_{i, 0},第4个式子表示买主件m_i并且还买附件m_{i, 1},第5个式子表示买主件m_i并且还买附件m_{i, 0}m_{i, 1}

#include <stdio.h>

struct Device
{
    int price;
    int priority;
};

struct MasterDevice
{
    int id;
    struct Device master;
    struct Device attachment[2];
    int num_attachment;
};

int max(int a, int b)
{
    return a > b ? a : b;
}

int main()
{
    int N, m, v, p, q;
    struct MasterDevice items[62];
    int num_master = 0;
    int f[62][32005] = { 0 };

    scanf("%d %d", &N, &m);
    for (int i = 1; i <= m; ++i)
    {
        scanf("%d %d %d", &v, &p, &q);
        if (q == 0)
        {
            ++num_master;
            items[num_master].id = i;
            items[num_master].master.price = v;
            items[num_master].master.priority = p;
            items[num_master].num_attachment = 0;
        }
        else
        {
            for (int k = 1; k <= num_master; ++k)
            {
                if (items[k].id == q)
                {
                    items[k].attachment[items[k].num_attachment].price = v;
                    items[k].attachment[items[k].num_attachment].priority = p;
                    items[k].num_attachment++;
                    break;
                }
            }
        }
    }

    for (int i = 1; i <= num_master; ++i)
    {
        for (int j = 1; j <= N; ++j)
        {
            f[i][j] = f[i-1][j];
            if (j - items[i].master.price >= 0)
                f[i][j] = max(f[i][j],
                              f[i-1][j-items[i].master.price] +
                                      items[i].master.price * items[i].master.priority);
            if (items[i].num_attachment == 1)
            {
                if (j - items[i].master.price - items[i].attachment[0].price >= 0)
                    f[i][j] = max(f[i][j],
                                  f[i-1][j-items[i].master.price-items[i].attachment[0].price] +
                                          items[i].master.price * items[i].master.priority +
                                          items[i].attachment[0].price * items[i].attachment[0].priority);
            }
            else if (items[i].num_attachment == 2)
            {
                if (j - items[i].master.price - items[i].attachment[0].price >= 0)
                    f[i][j] = max(f[i][j],
                                  f[i-1][j-items[i].master.price-items[i].attachment[0].price] +
                                          items[i].master.price * items[i].master.priority +
                                          items[i].attachment[0].price * items[i].attachment[0].priority);
                if (j - items[i].master.price - items[i].attachment[1].price >= 0)
                    f[i][j] = max(f[i][j],
                                  f[i-1][j-items[i].master.price-items[i].attachment[1].price] +
                                          items[i].master.price * items[i].master.priority +
                                          items[i].attachment[1].price * items[i].attachment[1].priority);
                if (j - items[i].master.price - items[i].attachment[0].price - items[i].attachment[1].price >= 0)
                    f[i][j] = max(f[i][j],
                                  f[i-1][j-items[i].master.price-items[i].attachment[0].price-items[i].attachment[1].price] +
                                          items[i].master.price * items[i].master.priority +
                                          items[i].attachment[0].price * items[i].attachment[0].priority +
                                          items[i].attachment[1].price * items[i].attachment[1].priority);
            }
        }
    }

    printf("%d", f[num_master][N]);

    return 0;
}
发布了298 篇原创文章 · 获赞 43 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/liulizhi1996/article/details/104197196