A.How much we can spend
题目定位及考察点
难度等级:C
考察点:优化算法复杂度的意识、对题意细节的把握
题意翻译
LYK、HYK、LCX终于可以去参加ACM-ICPC区域赛了,真的非常非常开心,特别是对于某位大四狗来说。但有个问题非常困扰他们——经费有限。学校只愿意为他们三人一共报销M元,这包含了来回车费以及住宿费。现在LYK需要你帮他规划一下,怎样的消费方式组合(南昌到上海的交通方式、在上海的住宿方式、上海回南昌的交通方式)可以使得报销费用最大而且又不需要自己掏钱。注意,三位队员的交通方式、住宿方式必须一致。
第一行会输入一个整数N,代表测试样例的组数,N取值范围是1到100。每一组测试样例的第一行包含四个整数,之间用空格隔开,分别是M、A、B、C。M代表学校的报销上限。A代表南昌到上海的交通方式有多少种。B代表住宿方式有多少种。C代表上海回南昌的交通方式有多少种。A、B、C的取值范围在0到1000之间(不包含0)。M取值范围在0到10000之间(不含0)。接下来有三行整数,第一行有A个整数,代表南昌到上海每种交通方式的费用;第二行有B个整数,代表每种住宿方式的费用;第三行有C个整数,代表上海回南昌每一种交通方式的费用。费用的取值都在0到10000之间。
对于每组样例,输出一种符合题意的消费组合方式的金额。每组输出单独占一行。若无法找到此组合,输入“Sorry,you can not go to shanghai”(不包含双引号)。
解题思路
看完题目以后我们可以把题意抽象为这样的一个数学问题:对于一个给定的数K,在集合A中抽取一个数x1,在集合B中抽取一个数x2,在集合C中抽取一个数x3,使得
3*(x1+x2+x3)<=K并且x1+x2+x3的值最大。
一种非常直观的粗暴做法就是,枚举集合A、B和C中的每一个元素,求和,如果满足3*(x1+x2+x3)<=K,那么就更新最大值。当集合枚举完以后,答案就出来了。但这道题的数据规模是10^3,如果用这么粗暴的做法那时间复杂度将会达到O(10^9),而且还有100组测试数据,那总的时间复杂度将会达到O(10^11),一定会超时的。那怎么优化呢?
三个集合都枚举显然超时,那枚举两个集合又会如何呢?如果我们把集合A和集合B中的每一个元素进行枚举求和,得出的元素放入集合SUM中,那么数学模型就可以变为SUM+x3<=K了,做个变形,x3<=K-SUM。所以我们可以在集合C中二分搜索K-SUM,这个二分的时间复杂度是O(log10^3),于是我们的时间复杂度可以从O(10^11)降到O(3×10^8),完全可以了。
对新生的话
ACM比赛考察点无非是算法知识和算法思维,这其中包含优化算法时间复杂度的思维。所以当你们看到一道非常简单的题目时,不要急着立马写代码,要判断一下时间复杂度是否满足要求、是否需要优化?否则可能就吃掉很多个TLE都不知道跪在哪里了。
给你们个建议,做完一道题目以后不要仅仅着眼于这道题学到什么知识点,还可以去品味一下这道题用了哪些算法思想,这样做可能对你们的得益会更大一些。