• 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 }
  • 相关阅读:
    A working example of bad SQL statement causes too much CPU usage
    Notes on <<Refactoring Databases Evolutionary Database Design>>
    DBMS_SQL & ORA01000: Too many open cursors
    TTS, not used for schema exp/imp
    Notes on <High Performance MySQL> Ch6: Optimizing Server Settings
    Notes on <High Performance MySQL> Ch3: Schema Optimization and Indexing
    A bug of "sql*loader"?
    11.2.0.2 improves the support for MERGE statement
    Use "OR" in SQL with caution
    关于NORFLASH和NANDfLASH的区别。——Arvin
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12249327.html
Copyright © 2020-2023  润新知