HDU 1864 最大报销额(01背包,烂题)

时间:2021-11-30 18:44:58

 

 

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

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

 

 

HDU 1864 最大报销额(01背包,烂题)HDU 1864 最大报销额(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\n",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了。

 

HDU 1864 最大报销额(01背包,烂题)HDU 1864 最大报销额(01背包,烂题)
 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\n",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 }
限额作为背包容量

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