zoukankan      html  css  js  c++  java
  • P1064 金明的预算方案 (背包)

    题目链接

     

    题解:

    对每种主件的 附件的集合 进行一次 01 背包处理,就可以先求出 对于每一种主件包括其附件的组合中,每种花费的最大价值,对应不同的方案。

    在对主件进行背包处理。

    需要注意的是在对每个主件的附件进行处理时,要恰好花完价钱,否则方案数会非常多。

    Code:

     1 #include <bits/stdc++.h>
     2 # define LL long long
     3 using namespace std;
     4 
     5 const int maxn=65;
     6 int N, m;
     7 
     8 struct Obj{
     9     int v,p,q;
    10 }arr[maxn];;
    11 Obj fujian[maxn][5]; //主件的附件信息
    12 int fcnt[maxn];  //主件的附件个数
    13 int f[33000];    //i价钱取得的最大价值
    14 int V[maxn][5];   //主件的不同方案需要的价钱
    15 int P[maxn][5];   //主件的不同方案获得的价值
    16 int pcnt[maxn];   //各个主件的方案数
    17 
    18 int main(){
    19     scanf("%d %d", &N, &m);
    20     int a,b,c;
    21     for(int i=1;i<=m;++i){
    22         scanf("%d %d %d", &a, &b, &c);
    23         arr[i].v=a;
    24         arr[i].p=b;
    25         arr[i].q=c;
    26         if(c>0){
    27             fcnt[c]++;
    28             fujian[c][fcnt[c]].v=a;
    29             fujian[c][fcnt[c]].p=b;
    30             fujian[c][fcnt[c]].q=c;
    31         }
    32     }
    33     for(int i=1;i<=m;++i){   //处理主件及其相应附件
    34         if(arr[i].q==0){
    35             //只取主件
    36             ++pcnt[i];
    37             V[i][pcnt[i]]=arr[i].v;
    38             P[i][pcnt[i]]=arr[i].v*arr[i].p;
    39 
    40             //考虑取不同附件
    41             memset(f,-1,sizeof(f));
    42             f[0]=0;
    43             for(int j=1;j<=fcnt[i];++j){
    44                 for(int k=N-arr[i].v;k>=fujian[i][j].v;--k){
    45                     if(f[k-fujian[i][j].v]!=-1)
    46                         f[k]=max(f[k],f[k-fujian[i][j].v]+fujian[i][j].v*fujian[i][j].p);
    47                 }
    48             }
    49 
    50             for(int j=0;j<=N-arr[i].v;++j){  //不同价钱对应的价值,即不同的方案
    51                 if(f[j]!=-1){
    52                     ++pcnt[i];
    53                     V[i][pcnt[i]]=arr[i].v+j;
    54                     P[i][pcnt[i]]=arr[i].v*arr[i].p+f[j];
    55                 }
    56             }
    57         }
    58     }
    59     memset(f,0,sizeof(f));
    60     for(int i=1;i<=m;++i){
    61         if(arr[i].q==0){
    62             for(int j=N;j>=arr[i].v;--j){
    63                 for(int k=1;k<=pcnt[i];++k){
    64                     if(j>=V[i][k]){
    65                         f[j]=max(f[j],f[j-V[i][k]]+P[i][k]);
    66                     }
    67                 }
    68             }
    69         }
    70     }
    71     printf("%d", f[N]);
    72     return 0;
    73 }

    注意到题目说只有三种情况,每个主件可以有0个、1个或2个附件。

    所以可以这样写:

     1 #include <bits/stdc++.h>
     2 # define LL long long
     3 using namespace std;
     4 
     5 const int maxn=65;
     6 int N, m;
     7 
     8 struct Obj{
     9     int v,p,q;
    10 }arr[maxn];;
    11 Obj fujian[maxn][5]; //主件的附件信息
    12 int fcnt[maxn];  //主件的附件个数
    13 int f[33000];    //i价钱取得的最大价值
    14 int V[maxn][5];   //主件的不同方案需要的价钱
    15 int P[maxn][5];   //主件的不同方案获得的价值
    16 int pcnt[maxn];   //各个主件的方案数
    17 
    18 int main(){
    19     scanf("%d %d", &N, &m);
    20     int a,b,c;
    21     for(int i=1;i<=m;++i){
    22         scanf("%d %d %d", &a, &b, &c);
    23         arr[i].v=a;
    24         arr[i].p=b;
    25         arr[i].q=c;
    26         if(c>0){
    27             fcnt[c]++;
    28             fujian[c][fcnt[c]].v=a;
    29             fujian[c][fcnt[c]].p=b;
    30             fujian[c][fcnt[c]].q=c;
    31         }
    32     }
    33     
    34     for(int i=1;i<=m;++i){
    35         if(arr[i].q==0){
    36             for(int j=N;j>=arr[i].v;--j){
    37                 f[j]=max(f[j],f[j-arr[i].v]+arr[i].v*arr[i].p);
    38 
    39                 if(fcnt[i]>0 && j-arr[i].v-fujian[i][1].v>=0){
    40                     f[j]=max(f[j],f[j-arr[i].v-fujian[i][1].v]+arr[i].v*arr[i].p+fujian[i][1].v*fujian[i][1].p);
    41                 }
    42                 if(fcnt[i]>1 && j-arr[i].v-fujian[i][2].v>=0){
    43                     f[j]=max(f[j],f[j-arr[i].v-fujian[i][2].v]+arr[i].v*arr[i].p+fujian[i][2].v*fujian[i][2].p);
    44 
    45                     if(j-arr[i].v-fujian[i][2].v-fujian[i][1].v>=0){
    46                         f[j]=max(f[j],f[j-arr[i].v-fujian[i][2].v-fujian[i][1].v]+arr[i].v*arr[i].p+fujian[i][2].v*fujian[i][2].p
    47                         +fujian[i][1].v*fujian[i][1].p);
    48                     }
    49                 }
    50             }
    51         }
    52     }
    53     printf("%d", f[N]);
    54     return 0;
    55 }
  • 相关阅读:
    mysql 中只能使用 localhost 登录,用ip不能登陆
    在springboot 和 mybatis 项目中想要显示sql 语句进行调试
    从一张表数据导入到另一张表
    mysql 中 delete 子查询的限制
    配置eureka 老是报错connected time out 或者 refused connected
    Linux-TCP 出现 RST 的几种情况
    MySQL-优化之 index merge(索引合并)
    Python-Mac 安装 PyQt4
    PHP-PHP-FPM的max_children一些误区
    Linux-磁盘及网络IO工作方式解析
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12249327.html
Copyright © 2011-2022 走看看