计蒜之道2015程序设计大赛初赛第四场——爱奇艺的自制节目

(一)题面

爱奇艺作为一家视频网站巨头,要为上亿的用户每天都提供“悦享品质”的服务。除了引进一些优秀的影视作品外,爱奇艺还做了一些诸如奇葩说、晓松奇谈的自制节目。爱奇艺最近又准备制作四档新的节目,它们分别是 W, X, Y, Z;但是现在能用来录这些节目的演播室只有两个,分别是演播室 A 和演播室 B。

W 节目的现场搭建比较复杂,每一期都要在演播室 A 来录制,X 节目的摄影机位调整会影响节目质量,每一期都固定在演播室 B 来录制。而节目 Y 和节目 Z 的搭建都比较容易移动,摄影也没有特别的要求,既可以在演播室 A 录制,也可以在演播室 B 录制。

已知 W 节目一共 Ew 期,每期录制需要 w 分钟;X 节目一共 Ex期,每期录制需要 x 分钟;Y 节目一共 Ey 期,每期录制需要 y 分钟;Z 节目一共 Ez 期,每期录制需要 z 分钟。

每一期节目从开始到结束必须在同一个演播室内录制,而整个节目不必每一期都在同一个演播室内录制。现在爱奇艺希望在最短时间内在这两个演播室内将四档节目录制完成,在节目都连续录制的假设下,你能帮他们算出将节目全部录制完成所需的最短时间么?

输入格式

第一行输入一个整数 T (1 ≤ T ≤ 50),表示数据组数。

接下来一共输入 T 行数据,每行输入一组 8 个整数 Ew, Ex, Ey, Ez, w, x, y, z (1 ≤ Ew, Ex, Ey, Ez, w, x, y, z ≤ 106)。

输出格式

输出 T 行,每行一个整数,表示该组四档节目在连续录制的假设下,全部录完所需要的最短时间。

样例1

输入:

1
100 1 3 5 10 1 10 10

输出:

1000

(二)参考源码

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     private static final Scanner READER = new Scanner(System.in);
 5     private static final String LINE_SEPARATOR = System
 6             .getProperty("line.separator");
 7 
 8     public static void main(String[] args) {
 9         int T = READER.nextInt();
10         // 开始读下一行
11         READER.nextLine();
12         StringBuilder builder = new StringBuilder();
13         while (T-- > 0) {
14             String[] line = READER.nextLine().split(" ");
15             int E_w = Integer.parseInt(line[0]);
16             int E_x = Integer.parseInt(line[1]);
17             int E_y = Integer.parseInt(line[2]);
18             int E_z = Integer.parseInt(line[3]);
19             int W = Integer.parseInt(line[4]);
20             int X = Integer.parseInt(line[5]);
21             int Y = Integer.parseInt(line[6]);
22             int Z = Integer.parseInt(line[7]);
23 
24             // 上面的效率更高
25             // int E_w = READER.nextInt();
26             // int E_x = READER.nextInt();
27             // int E_y = READER.nextInt();
28             // int E_z = READER.nextInt();
29             // int W = READER.nextInt();
30             // int X = READER.nextInt();
31             // int Y = READER.nextInt();
32             // int Z = READER.nextInt();
33 
34             /*
35              * 假设节目Y在演播室A录t期,节目Z在演播室B录s期 则在演播室A的用时:A=Y*t+Z*s+E_w*W
36              * 则在演播室B的用时:B=Y*(E_y-t)+Z*(E_z-s)+E_x*X
37              * 目标是|A-B|最小,|A-B|=|E_w*W-E_x*X-E_y*Y-E_z*Z+2*Y*t+2*Z*s|
38              */
39             // E=E_w*W-E_x*X-E_y*Y-E_z*Z
40             long E = (long) E_w * W - (long) E_x * X - (long) E_y * Y
41                     - (long) E_z * Z;
42 
43             // t的下限
44             int t_low = Math.min(
45                     Math.max(
46                             (int) Math.floor((double) (-E - (long) E_z
47                                     * (Z << 1))
48                                     / (Y << 1)), 0), E_y);
49             // s的下限
50             int s_low = Math.min(
51                     Math.max(
52                             (int) Math.floor((double) (-E - (long) E_y
53                                     * (Y << 1))
54                                     / (Z << 1)), 0), E_z);
55             // t的上限
56             int t_upper = Math.min(
57                     Math.max((int) Math.ceil((double) -E / (Y << 1)), 0), E_y);
58             // s的上限
59             int s_upper = Math.min(
60                     Math.max((int) Math.ceil((double) -E / (Z << 1)), 0), E_z);
61             int t0 = 0;
62             int s0 = 0;
63             // |A-B|的最小值
64             long A_B_min = -1;
65             // 遍历t的所有取值,s取使|A-B|最接近0的整数
66             for (int t = t_upper; t >= t_low; t--) {
67                 double j = (double) (-E - (long) t * (Y << 1)) / (Z << 1);
68                 int s = Math.min(Math.max((int) Math.round(j), s_low), s_upper);
69                 long A_B = Math.abs(E + (long) t * (Y << 1) + (long) s
70                         * (Z << 1));
71                 if (A_B < A_B_min || A_B_min < 0) {
72                     A_B_min = A_B;
73                     t0 = t;
74                     s0 = s;
75                 }
76             }
77 
78             long E_min = Math.max((long) Y * t0 + (long) Z * s0 + (long) E_w
79                     * W, (long) Y * (E_y - t0) + (long) Z * (E_z - s0)
80                     + (long) E_x * X);
81             builder.append(E_min).append(LINE_SEPARATOR);
82         }
83         System.out.println(builder.toString());
84     }
85 }
Java