Google Code Jam Round 1A 2015 解题报告

题目链接:https://code.google.com/codejam/contest/4224486/

 

Problem A. Mushroom Monster

这题题意就是,有N个时间点,每个时间点,Kaylin可以吃掉一定数量的mushroom,Bartholomew可以放入任意数量的mushroom。

现在给出N个时间点分别有多少mushroom。

问:若Kaylin每个时间点可以吃任意数量的mushroom,那为了配合每个时间点的mushroom,Kaylin最少要吃掉多少蘑菇。

问:若Kaylin已恒定速度吃mushroom(即在每个时间点间吃的数量相同,若盘子空了则暂停进食),那为了配合每个时间点的mushroom,Kaylin最少要吃掉多少蘑菇。

 

看懂题目就是水题,第一问,只要吃掉下一个时间点相对于当前时间点减少的mushroom数量。

第二问,只要保证吃的速度要大于等于所有时间点mushroom减少的数量,即取需求速度最大值。

 

代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <numeric>
 6 #include <queue>
 7 using namespace std;
 8 
 9 const int MAXN = 1010;
10 const int INF = 0x3f3f3f3f;
11 
12 int a[MAXN], maxr[MAXN];
13 int T, n;
14 
15 int solve1() {
16     int res = 0;
17     for(int i = 0; i < n - 1; ++i)
18         res += max(0, a[i] - a[i + 1]);
19     return res;
20 }
21 
22 int solve2() {
23     int spd = 0;
24     for(int i = 0; i < n - 1; ++i)
25         spd = max(spd, a[i] - a[i + 1]);
26     int res = 0;
27     for(int i = 0; i < n - 1; ++i)
28         res += min(a[i], spd);
29     return res;
30 }
31 
32 int main() {
33     freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
34     scanf("%d", &T);
35     for(int t = 1; t <= T; ++t) {
36         scanf("%d", &n);
37         for(int i = 0; i < n; ++i)
38             scanf("%d", &a[i]);
39         maxr[n] = 0;
40         for(int i = n - 1; i >= 0; --i)
41             maxr[i] = max(maxr[i + 1], a[i]);
42         printf("Case #%d: %d %d\n", t, solve1(), solve2());
43     }
44 }
View Code

 

Problem B. Haircut

题目大意:已知有B个理发师,和B个理发师给任意一个人理发所需要的时间。现在有N个人在排队,若处于队首,会找当前不是正在理发的编号最小的理发师理发。

问:处于队列第N个的人会找第几个理发师。

 

思路:二分时间 time,计算在time个单位时间里,有sum人已经或正在理发,又有cnt个理发师恰好没有正在理发的人。

那么,若sum + cnt ≥ N,那么第N个人在前 time 个单位时间里,一定有机会开始理发。

如此二分可以得到第N个人开始理发的时间,再由上述的sum、cnt可以得到第N个人让第几个理发师理发。

 

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 const int MAXN = 1010;
 9 
10 int a[MAXN];
11 int T, n, b;
12 
13 bool check(LL k) {
14     LL sum = 0, cnt = 0;
15     for(int i = 0; i < b; ++i) {
16         cnt += (k % a[i] == 0);
17         sum += (k - 1) / a[i] + 1;
18     }
19     return sum + cnt >= n;
20 }
21 
22 int solve() {
23     LL l = 0, r = LL(n) * *max_element(a, a + b);//1000000;//
24     while(l < r) {
25         LL mid = (l + r) >> 1;
26         if(!check(mid)) l = mid + 1;
27         else r = mid;
28     }
29     LL sum = 0, p = 0;
30     for(int i = 0; i < b; ++i)
31         sum += (l - 1) / a[i] + 1;
32     for(int i = 0; i < b; ++i)
33         if(l % a[i] == 0 && sum + ++p == n) return i + 1;
34     return -1;
35 }
36 
37 int main() {
38     freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
39     scanf("%d", &T);
40     for(int t = 1; t <= T; ++t) {
41         scanf("%d%d", &b, &n);
42         for(int i = 0; i < b; ++i)
43             scanf("%d", &a[i]);
44         printf("Case #%d: %d\n", t, solve());
45     }
46 }
View Code

 

Problem C. Logging

给N个点,分别问对于每个点来说,至少删掉多少个点,能使该点在剩下的点的凸包的边上。

 

思路1:因为凸包的边的性质是:对于一条边,每个点都在其同侧。那么,O(n^2)枚举所有边,O(n)枚举所有点,看要删掉那些点。复杂度O(n^3),可以跑过小数据,牛叉的电脑可以过大数据(RMB玩家与贫民玩家的区别就体现在这里了!)

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <vector>
 7 using namespace std;
 8 typedef long long LL;
 9 
10 const int MAXN = 3010;
11 
12 struct Point {
13     int x, y, id;
14     Point() {}
15     Point(int x, int y): x(x), y(y) {}
16     void read(int i) {
17         id = i;
18         scanf("%d%d", &x, &y);
19     }
20     Point operator - (const Point &rhs) const {
21         return Point(x - rhs.x, y - rhs.y);
22     }
23     bool operator < (const Point &rhs) const {
24         if(y != rhs.y) return y < rhs.y;
25         return x < rhs.x;
26     }
27 };
28 
29 LL cross(const Point &a, const Point &b) {
30     return (LL)a.x * b.y - (LL)a.y * b.x;
31 }
32 //ret >= 0 means turn right
33 LL cross(const Point &op, const Point &sp, const Point &ed) {
34     return cross(sp - op, ed - op);
35 }
36 
37 Point p[MAXN];
38 int ans[MAXN];
39 int n, top, T;
40 
41 void update_min(int &a, int b) {
42     if(a > b) a = b;
43 }
44 
45 void solve() {
46     for(int i = 0; i < n; ++i) for(int j = i + 1; j < n; ++j) {
47         int lsum = 0, rsum = 0;
48         for(int k = 0; k < n; ++k) {
49             LL t = cross(p[i], p[j], p[k]);
50             if(t > 0) lsum++;
51             if(t < 0) rsum++;
52         }
53         update_min(ans[i], min(lsum, rsum));
54         update_min(ans[j], min(lsum, rsum));
55     }
56 }
57 
58 int main() {
59     freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
60     scanf("%d", &T);
61     for(int t = 1; t <= T; ++t) {
62         scanf("%d", &n);
63         for(int i = 0; i < n; ++i)
64             p[i].read(i), ans[i] = n - 1;
65         solve();
66         printf("Case #%d:\n", t);
67         for(int i = 0; i < n; ++i)
68             printf("%d\n", ans[i]);
69     }
70 }
View Code

 

思路2:枚举每一个点,其他点绕枚举点排序,用一条过枚举点的直线旋转,计算要删掉的最少点。复杂度O(n^2logn)。

代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cmath>
 6 using namespace std;
 7 typedef long long LL;
 8 
 9 struct Point {
10     int x, y;
11     Point() {}
12     Point(int x, int y): x(x), y(y) {}
13     Point operator - (const Point &rhs) const {
14         return Point(x - rhs.x, y - rhs.y);
15     }
16     double ang() const {
17         return atan2(y, x);
18     }
19     bool type() const {
20         if(y != 0) return y > 0;
21         return x < 0;
22     }
23 };
24 
25 LL cross(const Point &a, const Point &b) {
26     return (LL)a.x * b.y - (LL)a.y * b.x;
27 }
28 
29 const int MAXN = 3010;
30 
31 Point p[MAXN], v[MAXN << 1];
32 int n, T;
33 
34 bool cmp(const Point &a, const Point &b) {
35     if(a.type() != b.type()) return a.type() < b.type();
36     return cross(a, b) > 0;
37 }
38 
39 void solve(int n) {
40     for(int i = 1; i < n; ++i)
41         v[i - 1] = p[i] - p[0];
42     n--;
43     sort(v, v + n, cmp);
44     copy(v, v + n, v + n);
45     int res = 0;
46     for(int i = 0, j = 0; i < n; ++i) {
47         if(i == j) j++;
48         while(j < i + n && cross(v[i], v[j]) >= 0) ++j;
49         res = max(res, j - i);
50     }
51     printf("%d\n", n - res);
52 }
53 
54 int main() {
55     freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
56     scanf("%d", &T);
57     for(int t = 1; t <= T; ++t) {
58         scanf("%d", &n);
59         for(int i = 0; i < n; ++i)
60             scanf("%d%d", &p[i].x, &p[i].y);
61         printf("Case #%d:\n", t);
62         for(int i = 0; i < n; ++i) {
63             swap(p[0], p[i]);
64             solve(n);
65             swap(p[0], p[i]);
66         }
67     }
68 }
View Code

 

posted @ 2015-04-22 11:55  Oyking  阅读(356)  评论(0编辑  收藏  举报