zoukankan      html  css  js  c++  java
  • HDU 1864 最大报销额(01背包,烂题)

    题意:被坑惨,单项不能超过600,其实是一张发票上A类/B类/C类的总和分别不能超过600。

    思路:此题的数据很烂。用贪心也能过,用01背包也可以。都测试不出到底那些是错的。

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <math.h>
     6 #include <algorithm>
     7 using namespace std;
     8 const int N=31; //发票张数
     9 double money;
    10 int num,t;
    11 int A,B,C;
    12 double tick[N];
    13 
    14 int cmp(double a, double b)
    15 {
    16     return a>b?1:0;
    17 }
    18 void packet()
    19 {
    20     double ans=0;
    21     sort(tick, tick+t, cmp);
    22     for(int i=0; i<=t; i++)
    23     {
    24         if(money>=tick[i])
    25         {
    26             ans+=tick[i];    
    27             money-=tick[i];    
    28         }
    29     
    30     }
    31     printf("%.2lf
    ",ans);   
    32 
    33 }
    34 
    35 
    36 int main()
    37 {
    38     freopen("input.txt","r",stdin);
    39 
    40     int n,flag,u;
    41     double cnt=0, pri;            //只是用于计算每张发票总和
    42     char c,tmp;  
    43 
    44     while(cin>>money>>num&&num)
    45     {
    46         t=0;
    47         memset(tick, 0, sizeof(tick));
    48     
    49         for(int i=0; i<num; i++)    //发票
    50         {
    51             flag=1;cnt=0;A=B=C=0;
    52             
    53             cin>>n;
    54             for(int j=0; j<n; j++)  //发票项
    55             {
    56                 cin>>c>>tmp>>pri;
    57                 cnt+=pri;
    58                 
    59                 if(c=='A')
    60                     A+=pri;
    61                 else if(c=='B')
    62                     B+=pri;
    63                 else if(c=='C')
    64                     C+=pri;
    65                    else 
    66                        flag=0;
    67             }
    68             if( !flag || cnt>1000 || A>600 || B>600 || C>600 )
    69                 continue;
    70             else
    71                 tick[t++]=cnt;     
    72 
    73         }
    74         //以上都是输入的,重点在这个函数而已
    75         packet();
    76     }
    77     return 0;
    78 }
    贪心

    我觉得贪心应该不能过的,比如有数据:

    1001.5 4
    1 A:500
    1 C:400
    1 A:300
    1 B:200

    贪心的结果是900,而正确答案是1000=500+300+200.。神奇的是AC了。

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <math.h>
     6 using namespace std;
     7 const int N=31; //发票张数
     8 double money;
     9 double dp[30005];
    10 double tick[N];
    11 int num,t,A,B,C;
    12 
    13 void packet()
    14 {
    15     for(int i=0; i<t; i++)
    16     {
    17         for(int j=ceil(money); ((double)j)-tick[i]>=money-floor(money); j--)//直接用向上取整来决定背包容量
    18         {
    19             double tmp = j-tick[i];    //还能放的容量
    20             if( dp[int(ceil(tmp))] <= tmp && dp[int(ceil(tmp) )] + tick[i] <= money )
    21                 tmp = dp[int(ceil(tmp) )] + tick[i];
    22             else
    23                 tmp = dp[int(tmp)] + tick[i];
    24 
    25             dp[j]= max( tmp , dp[j] );
    26         }
    27     }
    28     printf("%.2lf
    ",dp[(int)ceil(money)]);   
    29 }
    30 
    31 int main()
    32 {
    33     freopen("input.txt","r",stdin);
    34     int n,flag,u;
    35     double cnt=0, pri;            //只是用于计算每张发票总和
    36     char c,tmp;  
    37     
    38     while(cin>>money>>num&&num)
    39     {
    40         t=0;
    41         memset(tick, 0, sizeof(tick));
    42         memset(dp, 0, sizeof(dp));
    43         
    44         for(int i=0; i<num; i++)    //发票
    45         {
    46             flag=1;cnt=0;A=B=C=0;
    47             cin>>n;
    48             for(int j=0; j<n; j++)  //发票项
    49             {
    50                 cin>>c>>tmp>>pri;
    51                 cnt+=pri;
    52                 if(c=='A')
    53                     A+=pri;
    54                 else if(c=='B')
    55                     B+=pri;
    56                 else if(c=='C')
    57                     C+=pri;
    58                    else 
    59                        flag=0;
    60             }
    61             if( !flag || cnt>1000 || A>600 || B>600 || C>600 )
    62                 continue;
    63             else
    64                 tick[t++]=cnt;     
    65         }
    66         packet();
    67     }
    68     return 0;
    69 }
    限额作为背包容量

    这个比上面的精确多了,至少上面的数据能测出正确答案。

  • 相关阅读:
    UESTC_秋实大哥与时空漫游 2015 UESTC Training for Graph Theory<Problem C>
    UESTC_秋实大哥带我飞 2015 UESTC Training for Graph Theory<Problem B>
    UESTC_秋实大哥与连锁快餐店 2015 UESTC Training for Graph Theory<Problem A>
    UESTC_酱神寻宝 2015 UESTC Training for Dynamic Programming<Problem O>
    UESTC_导弹拦截 2015 UESTC Training for Dynamic Programming<Problem N>
    [error] MFC错误不能将参数1从"const char [3]"转换为"const wchar_t *"
    DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏的详细解释
    error MSB4044: 未给任务“CppClean”的必需参数“FoldersToClean”赋值
    关于vs2008的error C2440
    MFC m_hWnd 和 this指针
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4472489.html
Copyright © 2011-2022 走看看