ZOJ 3703 Happy Programming Contest (01背包,稍微加点处理)

先按做完题目的时间排序,在确定自己要做哪些题后,先做时间短的,这样能保证等的时间是最短的,在这里,能保证罚时会是最少的。然后0-1背包,0-1背包时先只管价值最大,在背包完后当价值一样时,再管题目做的多,题目数量一样时再管罚时少。

贴代码,代码中有注释:

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define INF 0x7fffffff//int类型中最大的正整数
 5 using namespace std;
 6 struct node1
 7 {
 8     int time,value;//时间,价值
 9     bool operator < (const node1 & o)const
10     {
11         if(time < o.time) return true;
12         else return false;
13     }
14 } p[55];
15 struct node2
16 {
17     int value,q,endtime,penalty;//价值,题目数量,结束时间,罚时
18 } f[1005];//f[i]中的i表示为时间限制为i
19 int main()
20 {
21 //    freopen("in.cpp","r",stdin);
22     int r;
23     scanf("%d",&r);
24     while(r--)
25     {
26         int l,num;
27         scanf("%d%d",&l,&num);
28         for(int i=0; i<num; ++i)
29             scanf("%d",&p[i].time);
30         for(int i=0; i<num; ++i)
31             scanf("%d",&p[i].value);
32         sort(p,p+num);//排序
33         for(int i=0; i<=l; ++i)//0-1背包的恰好装满型
34         {
35             f[i].value = -INF;//初始值为负无穷
36             f[i].q = 0;
37             f[i].endtime= 0;
38             f[i].penalty = 0;
39         }
40         f[0].value = 0;//只有容量为0的初始值为0
41         for(int i=0; i<num; ++i)
42         {
43             for(int j=l; j >= p[i].time; --j)
44             {
45                 int w =j-p[i].time;
46                 if(f[w].value + p[i].value > f[j].value)
47                 {
48                     f[j].value = f[w].value + p[i].value;
49                     f[j].q = f[w].q +1;
50                     f[j].endtime = f[w].endtime + p[i].time;//该题的结束时间
51                     //做到这个题的罚时=做到上题的罚时加上这题的结束时间
52                     f[j].penalty = f[w].penalty + f[j].endtime;
53                 }
54             }
55         }
56         node2 ans= {0,0,0};
57         for(int i=0; i<=l; ++i)
58         {
59             if(f[i].value > ans.value)//价值最大优先
60                 ans = f[i];
61             else if(f[i].value == ans.value )//价值一样
62             {
63                 if(f[i].q > ans.q)//做的题多的优先
64                     ans = f[i];
65                 else if(f[i].q  ==  ans.q && f[i].penalty < ans.penalty)//做的题数量一样后
66                     //罚时少的优先
67                     ans = f[i];
68             }
69         }
70         printf("%d %d %d\n",ans.value,ans.q,ans.penalty);//输出结果
71     }
72     return 0;
73 }
原文地址:https://www.cnblogs.com/allh123/p/3065603.html