• POJ 2184 Cow Exhibition 01背包变型 好题


    题意:n头牛,每头牛有两个属性值,smart值s,fun值f,求选出其中的m头牛,使得s和f的总和最大,并保证各自的s和以及f和都大于0.
    分析:
    怎么保证TS和TF都是>=0的条件下使得TS+TF最大?
    先保证TS和TF都是>=0,然后遍历一边取TS+TF的最大值就ok了。
     
    转化问题,求s和为某个固定值时候最大的f和值,然后遍历这些所有的s和以及对应的f和值,求出总和总和最大的那个。
    那么这样就是一个0-1背包问题,可以把s值理解为代价,f值理解为价值
     dp[c]代表s和为c时候,f和能取到的最大值。
    状态转移方程: dp[c]=max{dp[c], dp[c-s[i]+f[i]}
     
    注意:
    因为s有小于0的情况,s的范围在[-1000,1000]之间,最多有100头牛,所以和的范围在[-100000,100000]之间,为了避免负数作为下标,s和都加上100000,整体的范围就变为[0,200000]。
    当s[i]>0的时候,dp[c]的计算顺序从大往小计算,因为在计算第i头牛的最优f和时,dp[c-s[i]]是前i-1头牛的最优f和,而这个值在dp[c]的左侧,所以我们从右往左计算,这样就可以利用前i-1的最优解,不会覆盖。
    同理当s[i]<0的时候,dp[c]的计算顺序从小往大计算,因为dp[c-s[i]]这个时候dp[c]的右侧了。
     
     
     1 #include<cstdio>
     2 #include<cstring>
     3 
     4 const int maxn=200000+10;
     5 const int inf=0x3f3f3f3f;
     6 
     7 int dp[maxn];
     8 int s[105];
     9 int f[105];
    10 
    11 int max(int a,int b)
    12 {
    13     return a>b?a:b;
    14 }
    15 
    16 int main()
    17 {
    18     int n;
    19     while(~scanf("%d",&n))
    20     {
    21         int up=100000,down=100000;
    22         for(int i=1;i<=n;i++)
    23         {
    24             scanf("%d%d",&s[i],&f[i]);
    25             if(s[i]>0)
    26                 up+=s[i];
    27             else
    28                 down+=s[i];
    29         }
    30 
    31         for(int i=down;i<=up;i++)
    32             dp[i]=-inf;
    33         dp[100000]=0;
    34         for(int i=1;i<=n;i++)
    35         {
    36             if(s[i]<=0&&f[i]<=0)
    37                 continue;
    38             if(s[i]>0)
    39             {
    40                 for(int j=up;j>=down+s[i];j--)
    41                 {
    42                     dp[j]=max(dp[j],dp[j-s[i]]+f[i]);
    43                 }
    44             }
    45             else
    46             {
    47                 for(int j=down;j<=up+s[i];j++)
    48                 {
    49                     dp[j]=max(dp[j],dp[j-s[i]]+f[i]);
    50                 }
    51             }
    52         }
    53         int ans=0;
    54         for(int i=100000;i<=up;i++)
    55         {
    56             if(dp[i]>=0)
    57                 ans=max(ans,i+dp[i]-100000);
    58         }
    59         printf("%d
    ",ans);
    60     }
    61     return 0;
    62 }
    View Code
     
     
  • 相关阅读:
    Spring bean相关
    Springboot消除switch-case方法
    Springcloud中的region和zone的使用
    SpringCloud-Eureka-服务注册是如何发起的
    SpringBoot-SpringCloud-版本对应关系
    SpringCloud-Eureka-Provider&Consumer
    激活IDEA
    搞懂spring事务
    部署spring Boot项目到tomcat
    springBoot项目打war包部署到tomcat上
  • 原文地址:https://www.cnblogs.com/-maybe/p/4692556.html
Copyright © 2020-2023  润新知