• DP——背包问题(三)


    终于到了有附带条件的背包问题了,现在讲一个很简单的带有主件、附件的问题的背包问题的解法……这道题我一直拖了一年都没有写……

    题意:
    有m件物品,其中有主件,有附件,每个主件的附件最多2个,只有选了主件才能选附件,不能单独选附件。每件物品有重要性和需要花费的钱数,他的价值是重要性和需要花费的钱数的积……现在有n元钱,要求买到的物品价值之和最大。

    输入格式:

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

    对于这道题的物品可以进行以下处理:

    首先,将所有主件挑出来,主件就最多有4种选择:只要主件;要主件和一号附件;要主件和二号附件;要主件和一号和二号附件;

    这样一来,就相当于把问题从“选”与“不选”转化为“选哪种方案”,在利用01背包,就能快速求解;

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<string>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<algorithm>
     7 using namespace std;
     8 
     9 int dp[600000],n,m,w,ge,pp,ppp;
    10 int fn[1000][1000][2];
    11 int fnn[1000];
    12 int v[1000],cun[100];
    13 struct ez{
    14     int vy;
    15     int w;
    16     int p;
    17 } a[100];
    18 
    19 int main(){
    20     scanf("%d %d",&n,&m);
    21     n=n/10;
    22     for(int i=1;i<=m;i++) scanf("%d %d %d",&a[i].w,&a[i].vy,&a[i].p);
    23     for(int i=1;i<=m;i++){
    24         a[i].w/=10;
    25         if(a[i].p==0){
    26             ge++;
    27             cun[i]=ge;
    28             fnn[ge]++;
    29             fn[ge][fnn[ge]][0]=a[i].vy*a[i].w;
    30             fn[ge][fnn[ge]][1]=a[i].w;
    31         }else{
    32             ppp=fnn[cun[a[i].p]];
    33             while(fnn[cun[a[i].p]]-ppp+1<=ppp){
    34                 fnn[cun[a[i].p]]++;
    35                 fn[cun[a[i].p]][fnn[cun[a[i].p]]][1]=fn[cun[a[i].p]][fnn[cun[a[i].p]]-ppp][1]+a[i].w;
    36                 fn[cun[a[i].p]][fnn[cun[a[i].p]]][0]=fn[cun[a[i].p]][fnn[cun[a[i].p]]-ppp][0]+a[i].vy*a[i].w;    
    37             }
    38         }
    39     }
    40     for(int i=1;i<=ge;i++)
    41     for(int j=n;j>=1;j--)
    42     for(int k=1;k<=fnn[i];k++){
    43         if(j>=fn[i][k][1]) dp[j]=max(dp[j],dp[j-fn[i][k][1]]+fn[i][k][0]);
    44     }
    45     cout<<dp[n]*10<<endl;
    46     return 0;
    47 }
  • 相关阅读:
    spark编译
    使用MapReduce实现两个文件的Join操作
    响应式 Web 设计
    响应式 Web 设计
    900W+数据只用300ms搞定!SQL查询优化这样做最快耗时347ms
    响应式 Web 设计
    CSS3 多媒体查询实例
    CSS3 多媒体查询:查找设备的类型,CSS3 根据设置自适应显示
    CSS3 弹性盒子(Flex Box):确保元素拥有恰当的行为的布局方式
    CSS3 框大小:padding(内边距) 和 border(边框)
  • 原文地址:https://www.cnblogs.com/Misaki-Mei/p/7623893.html
Copyright © 2020-2023  润新知