2017 google Round C APAC Test 题解

题解参考网上的答案,以及我自己的想法。

主要参考网站:http://codeforces.com/blog/entry/47181http://codeforces.com/blog/entry/47185。讲的都非常仔细,我建议看这个上面的题解,开拓思路,然后就是看排行榜上大神们的答案,当然可以直接看下面我的题解。

第一题

1.看懂题意很重要,如果理解了怎么计算,代码应该很快就写出来。maximum possible expected number,求最大期望个数,就是一个位置可以访问多次,根据单次捕获的概率p,则期望有:e = p + (1 - p) * p + (1 - p)^2 * p + ....分别对应访问第一次,第二次,第三次,第四次,把这些加起来就是期望。然后写一个简单的dfs就可以,因为step比较小,大数据也很快可以跑完。

 1 /*
 2 ID: y1197771
 3 PROG: test
 4 LANG: C++
 5 */
 6 #include<bits/stdc++.h>
 7 #define pb push_back
 8 #define FOR(i, n) for (int i = 0; i < (int)n; ++i)
 9 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
10 typedef long long ll;
11 using namespace std;
12 typedef pair<int, int> pii;
13 const int maxn = 1e3 + 10;
14 bool e[25][25];
15 int vis[25][25];
16 int r, c, s, rs, cs;
17 double p, q;
18 double res;
19 int dx[] = {-1, 0, 1, 0};
20 int dy[] = {0, 1, 0, -1};
21 void dfs(int x, int y, int step, double v) {
22     if(step == 0) {
23         res = max(res, v);
24          return;
25     }
26     for (int i = 0; i < 4; i++) {
27         int cx = x + dx[i];
28         int cy = y + dy[i];
29         if(cx < 0 || cx >= r || cy < 0 || cy >= c) continue;
30         if(e[cx][cy]) {
31             vis[cx][cy]++;
32             double td = pow(1 - p, vis[cx][cy] - 1) * p;
33             dfs(cx, cy, step - 1, v + td);
34             vis[cx][cy]--;
35         } else {
36             vis[cx][cy]++;
37             double td = pow(1 - q, vis[cx][cy] - 1) * q;
38             dfs(cx, cy, step - 1, v + td);
39             vis[cx][cy]--;
40         }
41
42     }
43
44 }
45 void solve() {
46     cin >> r >> c >> rs >> cs >> s;
47     cin >> p >> q;
48     memset(e, 0, sizeof e);
49     memset(vis, 0, sizeof vis);
50     for (int i = 0; i < r; i++) {
51         for (int j = 0; j < c; j++) {
52             char ch; cin >> ch;
53             if(ch == ‘A‘) e[i][j] = 1;
54         }
55     }
56     res = 0;
57     dfs(rs, cs, s, 0);
58     printf("%.7f\n", res);
59 }
60 int main() {
61     freopen("test.in", "r", stdin);
62     freopen("test.out", "w", stdout);
63     int _;
64     cin >> _;
65     for (int i = 1; i <= _; i++) {
66         cout << "Case #" << i << ": ";
67         solve();
68     }
69
70     return 0;
71 }

2.读题,就是求全部为0的正方形的的个数,1代表有monster,然后这个问题跟maximize squarehttp://www.geeksforgeeks.org/maximum-size-sub-matrix-with-all-1s-in-a-binary-matrix/一样,这道题,我们用dp[i][j]来存储以i,j位置的小方块作为最右下角的正方形的个数,dp(i,j) represents the side length of the maximum square whose bottom right corner is the cell with index (i,j) in the original matrix. 递推公式跟前面这题是一样的,最后把所有的位置加起来即可。

递推公式:dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i][j]) + 1, if monster[i][j] = 0; dp[i][j] = 0, if monster[i][j] = 1. res = sum dp[i][j], 0 <= i < r, 0 <= j < c.

复杂度:r*c = 3000 * 3000 = 9000000, 很快就跑完了。

3. 理解什么是assignment variable和 variable arguments, 就是左边和右边的变量, 然后解题办法很多,比较简单,就是看所有的顶点是否可以到达,首先解析字符串表达式,构建图,然后计算所有的点是否都可以到达。这题注意入度为0的顶点,也就是a = f();这类的,可以构造一个伪节点,给右边没有变量的表达式添加一条从伪节点到左边变量的边,最后就是bfs或者dfs遍历,看所有的点是否都可以从伪节点到达。

  1 /*
  2 ID: y1197771
  3 PROG: test
  4 LANG: C++
  5 */
  6 #include<bits/stdc++.h>
  7 #define pb push_back
  8 #define FOR(i, n) for (int i = 0; i < (int)n; ++i)
  9 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
 10 typedef long long ll;
 11 using namespace std;
 12 typedef pair<int, int> pii;
 13 const int maxn = 1e3 + 10;
 14 int n;
 15 map<string, int> m;
 16 int num;
 17 int degree[maxn * 11];
 18 vector<int> e[maxn * 11];
 19 //set<int> e[maxn * 11];
 20 int get(string s) {
 21     if(m.count(s)) return m[s];
 22     m[s] = num++;
 23     e[num - 1].clear();
 24     return m[s];
 25 }
 26 set<int> se;
 27 void work(string s) {
 28     int t = s.find(‘=‘);
 29     string s1 = s.substr(0, t);
 30     //cout << s1 << endl;
 31     int head = get(s1);
 32     se.insert(head);
 33     int t1 = s.find(‘(‘);
 34     s = s.substr(t1 + 1);
 35     //cout << s << endl;
 36     auto it = s.find(‘,‘);
 37     while(it != string::npos) {
 38         s1 = s.substr(0, it);
 39         //cout << s1 << endl;
 40         int b = get(s1);
 41         e[b].pb(head);
 42         degree[head]++;
 43         s = s.substr(it + 1);
 44         it = s.find(‘,‘);
 45     }
 46     //cout << s << endl;
 47     it = s.find(‘)‘);
 48     s1 = s.substr(0, it);
 49     //cout << s1 << endl;
 50     if(s1.size() == 0) return;
 51     int b = get(s1);
 52     e[b].pb(head);
 53     degree[head]++;
 54
 55 }
 56 void solve() {
 57     cin >> n;
 58     m.clear(); se.clear();
 59     num = 0;
 60     memset(degree, 0, sizeof degree);
 61     string str;
 62     for (int i = 0; i < n; i++) {
 63         cin >> str;
 64         work(str);
 65     }
 66     {
 67         //for (auto i = m.begin(); i != m.end(); i++) {
 68          //   cout << i->first << " " << degree[i->second] << endl;
 69         //}
 70     }
 71     queue<int> q;
 72     for (int i = 0; i < num; i++) {
 73         if(degree[i] == 0) {
 74                 q.push(i);
 75             if(!se.count(i)) {
 76                 puts("BAD"); return;
 77             }
 78         }
 79     }
 80     while(!q.empty()) {
 81         int u = q.front(); q.pop();
 82         for (auto x : e[u]) {
 83             degree[x]--;
 84             if(degree[x] == 0) q.push(x);
 85         }
 86     }
 87     for (int i = 0; i < num; i++) {
 88         if(degree[i]) {
 89             puts("BAD"); return;
 90         }
 91     }
 92     puts("GOOD");
 93 }
 94 int main() {
 95     freopen("test.in", "r", stdin);
 96     freopen("test.out", "w", stdout);
 97     int _;
 98     cin >> _;
 99     for (int i = 1; i <= _; i++) {
100     cout << "Case #" << i << ": ";
101     solve();
102     }
103     return 0;
104 }

我当时做的有点麻烦,搞成拓扑排序了,其实也是正确的。

4. 读完题意,想到排序,但是不知道怎么排序,这个题目应该属于博弈游戏,nim之类的先手必胜,先手必败之类的,但是需要仔细分析情况,我当时没有搞明白。

后来看题解,原来是这样。

下面是cf上面大神的讲解,讲的非常清楚,仔细,我认为分析的特别透彻。

The solution to problem D is actually deceptively simple. Let‘s say whoever picks last wins.

If there are no soldiers, then Alice loses, because she has no moves. Otherwise, let the highest attack of the soldiers be maxA and the highest defense be maxD. We have two cases:

  • If there is a soldier with (Ai, Di) = (maxA, maxD), then Alice picks this soldier and wins immediately.
  • Otherwise, the players will never pick any soldier with attack maxA or defense maxD. The reason for this is that, if one player picks a soldier with attack maxA, the other immediately picks any soldier with defense maxD and wins. Therefore, as no soldiers with attack maxA or defense maxD will ever be picked, we can simply delete these soldiers and start again.

The straightforward O(n2) implementation is good enough, but it should be possible to implement this in  by sorting the soldiers first.

我看排行榜前几名的代码,感觉比较麻烦,也没去弄懂。这个比较简单。如果存在(maxA, maxD)的士兵,就是先手必胜。如果没有,然后就是单独最大的士兵,如果只有这些士兵,就是先手必败,后手必胜,可以直接返回0,如果还有其他的士兵,这些士兵决定了剩下的过程,删除掉前面的单独最大的士兵,然后重新开始,这时候就相当于重新开始一盘游戏,直接递归调用。

 1 /*
 2 ID: y1197771
 3 PROG: test
 4 LANG: C++
 5 */
 6 #include<bits/stdc++.h>
 7 #define pb push_back
 8 #define FOR(i, n) for (int i = 0; i < (int)n; ++i)
 9 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl
10 typedef long long ll;
11 using namespace std;
12 typedef pair<int, int> pii;
13 const int maxn = 4e3 + 10;
14 bool in[maxn];
15 int p[maxn][2];
16 int n;
17 int cnt = 0;
18 bool can(int x, int y) {
19     //cout << x << " " << y << endl;
20     //cnt++;
21     //if(cnt > 5) return 0;
22     int mx = x, my = y;
23     bool f = 0;
24     for (int i = 0; i < n; i++) {
25         if(!in[i]) {
26             f = 1;
27             mx = max(mx, p[i][0]);
28             my = max(my, p[i][1]);
29         }
30     }
31     if(!f) return false;
32     for (int i = 0; i < n; i++) {
33         if(!in[i]) {
34             if(p[i][0] == mx && p[i][1] == my) {
35                 return 1;
36             }
37         }
38     }
39     f = 0;
40     int id = 0;
41     for (int i = 0; i < n; i++) {
42         if(!in[i]) {
43             if(p[i][0] == mx || p[i][1] == my) continue;
44             id = i; f = 1; break;
45         }
46     }
47     if(!f) return 0;
48     for (int i = 0; i < n; i++) {
49         if(!in[i]) {
50             if(p[i][0] == mx || p[i][1] == my)
51                 in[i] = 1;
52         }
53     }
54     return can(0, 0);
55 }
56 void solve() {
57     cin >> n;
58     int x, y;
59     for (int i = 0; i < n; i++) {
60         cin >> x >> y;
61         p[i][0] = x, p[i][1] = y;
62         in[i] = 0;
63     }
64
65     if(can(0, 0)) {
66         cout << "YES" << endl;
67     } else {
68         cout << "NO" << endl;
69     }
70     //for (int i = 0; i < n; i++) {
71     //    cout << i << " " << in[i] << endl;
72     //}
73 }
74 int main() {
75     freopen("test.in", "r", stdin);
76     freopen("test.out", "w", stdout);
77     int _; cin >> _;
78     for (int i = 1; i <= _; i++) {
79         cout << "Case #" << i << ": ";
80         solve();
81     }
82
83     return 0;
84 }

上面是按照上面的思路写的代码,可以通过现在的大小数据,都是在1s内跑完的。代码写的比较丑,但是还是比较直接的。

总结:

这次比赛还是比较简单的,至少2,3题很容易,这2题的大小数据分数很容易拿到。第一题分析清楚期望,也是可以很快ac的,最后一题,就需要一些做题的经验,加上自己的分析,分析简单的样例,得出结果。

时间: 2024-10-12 15:20:45

2017 google Round C APAC Test 题解的相关文章

google Round D APAC Test 2017 题解

首先说明一下:我只是用暴力过了4道题的小数据,就是简单的枚举,大数据都不会做!下面的题解,是我从网上搜到的解答以及查看排行榜上大神的答案得出来的. 首先贴一下主要的题解来源:http://codeforces.com/blog/entry/47796,基本上解题思路都是从这里看到的,你可以直接查看这个链接,或者看下面的题解. 还有排行榜大神们的答案,https://code.google.com/codejam/contest/5264486/scoreboard?c=5264486#vf=1,

Google Round B APAC Test

A:题意密码由n不同的字符和m的长度组成,问你有多少种情况 解题思路:可以得到状态转移方程为  dp[i][j] = dp[i-1][j]*j + dp[i-1][j-1]*(n-j+1); 解题代码: 1 // File Name: a.cpp 2 // Author: darkdream 3 // Created Time: 2014年09月15日 星期一 14时29分39秒 4 5 #include<vector> 6 #include<list> 7 #include<

Yandex Algorithm 2017 Qualication Round (数组练习 + 拓扑排序练习)

Problem A. Task Management Input le: standard input Output le: standard output Time limit: 2 seconds Memory limit: 256 megabytes Sergey is Yandex junior software engineer for only several months, but he already completed n tasks. In order to manage t

Codeforces Round #262 (Div. 2) 题解

A. Vasya and Socks time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Vasya has n pairs of socks. In the morning of each day Vasya has to put on a pair of socks before he goes to school. When

Codeforces Round #FF (Div. 2) 题解

比赛链接:http://codeforces.com/contest/447 A. DZY Loves Hash time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output DZY has a hash table with p buckets, numbered from 0 to p?-?1. He wants to insert n 

Codeforces Round #259 (Div. 2) 题解

A. Little Pony and Crystal Mine time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Twilight Sparkle once got a crystal from the Crystal Mine. A crystal of size n (n is odd; n?>?1) is an n?×?n 

Codeforces Round #177 (Div. 2) 题解

[前言]咦?现在怎么流行打CF了?于是当一帮大爷在执着的打div 1的时候,我偷偷的在刷div 2.至于怎么决定场次嘛,一般我报一个数字A,随便再拉一个人选一个数字B.然后开始做第A^B场.如果觉得机密性不高,来点取模吧.然后今天做的这场少有的AK了.(其实模拟赛只做完了4题,最后1题来不及打了) 等等,话说前面几题不用写题解了?算了,让我难得风光一下啦. [A] A. Polo the Penguin and Segments time limit per test 2 seconds mem

Codeforces Round #534 (Div. 2)题解

Codeforces Round #534 (Div. 2)题解 A. Splitting into digits 题目大意 将一个数字分成几部分,几部分求和既是原数,问如何分可以使得分出来的各个数之间的差值尽可能小 解题思路 将n分成n个1相加即可 AC代码 #include<cstring> #include<string> #include<iostream> #include<cstdio> using namespace std; int main

Codeforces Round #561 (Div. 2) 题解

Codeforces Round #561 (Div. 2) 题解 题目链接 A. Silent Classroom 水题. Code #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 105; int n; char s[N], t[N]; int main() { cin >> n; for(int i = 1; i <= n; i++) { scanf(&q