• 洛谷p1064


    https://www.luogu.org/problemnew/show/P1064

    带有附件的背包问题,它属于01背包的变式。

    这题还好,每一个物品最多只有两个附件,那么我们在对主件进行背包的时候,决策就不再是两个了,而是五个。

    还记得01背包的决策是什么吗?

    1.不选,然后去考虑下一个

    2.选,背包容量减掉那个重量,总值加上那个价值。

    这个题的决策是五个,分别是:

    1.不选,然后去考虑下一个

    2.选且只选这个主件

    3.选这个主件,并且选附件1

    4.选这个主件,并且选附件2

    5.选这个主件,并且选附件1和附件2.

    这个。。。很好想吧。。。

    我们知道,01背包的状态转移方程(已使用滚动数组优化)是f[j] = max(f[j],f[j-w[i]]+c[i]),那么,这道题的转移方程也就不难写出了。

    等等,你得先判断某个选附件的决策是不是可行的,如果当前的容量还够放第一个,或第二个,或两个都选的附件,那么才能考虑转移。

    当然,不选附件的话就不用判啦,直接01背包的转移方程即可。

    我们令main_item_w数组表示某个主件的费用,而main_item_c数组表示某个主件的价值。

    同样的,用二维数组annex_item_w表示某个附件的费用,annex_item_c表示某个附件的价值,第二维只需要0,1,2这三个数,其中第二维是0的场合表示这个主件i的附件数量,它只能等于0或1或2。第二维是1或者是2的值代表以i为主件的附件1或者附件2的相关信息(费用 价值)。这些数组的信息应该在读入时处理好,具体详见代码。

    这样,状态转移方程就是四个。

    不选附件的①:f[j] = max(f[j],f[j-main_item_w[i]]+main_item_c[i]);

    选附件1的②:f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] ] + main_item_c[i] + annex_item_c[i][1]);

    选附件2的③:f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][2]);

    选附件1和附件2的④:f[j] = max(f[j],f[ j - main_item_w[i] - annex_item_w[i][1] - annex_item_w[i][2] ] + main_item_c[i] + annex_item_c[i][1] + annex_item_c[i][2]);

    已经滚动掉了第一维,道理和正常向的01背包都是一样的,即只有i和i-1有关系,但是这个规律在循环中已经满足了所以完全没必要记录。

    目标状态f[n],输出就好。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long ll;
     7 int f[30010];
     8 int n, m;
     9 int v, p, q;
    10 int ma[30010];
    11 int mac[30010];
    12 int an[30010][3];
    13 int anc[30010][3];
    14 int main()
    15 {
    16     cin >> n >> m;
    17     for (int i = 1; i <= m; i++)
    18     {
    19         cin >> v >> p >> q;
    20         if (q == 0)
    21         {
    22             ma[i] = v;
    23             mac[i] = v * p;
    24         }
    25         else
    26         {
    27             an[q][0]++;
    28             an[q][an[q][0]] = v;
    29             anc[q][an[q][0]] = v * p;
    30         }
    31     }
    32     for (int i = 1; i <= m; i++)
    33     {
    34         for (int j = n; j >= ma[i] && ma[i] != 0; j--)
    35         {
    36             f[j] = max(f[j], f[j - ma[i]] + mac[i]);
    37             if (j >= ma[i] + an[i][1])
    38             {
    39                 f[j] = max(f[j], f[j - ma[i] - an[i][1]] + mac[i] + anc[i][1]);
    40             }
    41             if (j >= ma[i] + an[i][2])
    42             {
    43                 f[j] = max(f[j], f[j - ma[i] - an[i][2]] + mac[i] + anc[i][2]);
    44             }
    45             if (j >= ma[i] + an[i][1] + an[i][2])
    46             {
    47                 f[j] = max(f[j], f[j - ma[i] - an[i][1] - an[i][2]] + mac[i] + anc[i][1] + anc[i][2]);
    48             }
    49         }
    50     }
    51     cout << f[n] << endl;
    52     return 0;
    53 }
  • 相关阅读:
    MySQL整理碎片
    华为云容器引擎 单实例模式部署 NACOS DOCKER
    NACOS DOCKER 官方镜像启动失败 No Datasource set
    nginx docker官方镜像使用自定义启动命令启动失败
    windows docker desktop配置国内镜像仓库
    SAP AUFM 针对订单的货物移动
    css 子元素margin-top影响了父元素
    HighCharts 嵌套仪表盘
    JAVA 使用JCO3调用SAP RFC函数
    线下WINDOWS主机挂载华为云存储
  • 原文地址:https://www.cnblogs.com/fengzhongzhuifeng/p/10827823.html
Copyright © 2020-2023  润新知