Google APAC Round D题解
来源:互联网 发布:模拟炒股 app 知乎 编辑:程序博客网 时间:2024/06/07 04:42
Problem A. Dynamic Grid
最基础的搜索,我用DFS做的,标记棋盘上每一个位置初始化为未搜索,遍历整个棋盘,如果遇到1且以前从没搜索到的话就从该点开始不停搜索,直到搜完,复杂度O(m*n)
代码
int m, n;int q;char b[110][110];bool flag[110][110];bool valid(int x ,int y){ if(x < 0 || x >= m) return false; if(y < 0 || y >= n) return false; if(flag[x][y] == 1) return false; if(b[x][y] != '1') return false; return true;}void DFS(int x ,int y){ flag[x][y] = 1; if(valid(x - 1, y)) DFS(x - 1, y); if(valid(x + 1, y)) DFS(x + 1, y); if(valid(x, y - 1)) DFS(x, y -1); if(valid(x, y + 1)) DFS(x, y + 1);}int solve(){ ZERO(flag); int count = 0; FOR(i,0,m) FOR(j,0,n) { if(b[i][j] == '1' && flag[i][j] == false) { DFS(i,j); count++; } } return count;}int main(){ int Tcase; cin >> Tcase; FOR(hh,0,Tcase) { cin >> m >> n; FOR(i,0,m) FOR(j,0,n) cin >> b[i][j]; cin >> q; cout << "Case #" << hh + 1 << ":" << endl; char ops; FOR(i,0,q) { cin >> ops; if(ops == 'Q') cout << solve() << endl; else { int x ,y; char val; cin >> x >> y >> val; b[x][y] = val; } } } return 0;}
Problem B. gBalloon
很有意思的题目,首先考虑不可能的情况:
1.如果风向和距离的乘积为正数或者0(距离不为0),那么一定需要移动这个气球(称之为坏球),记下所需要的最小的消耗,如果所有坏球所需最小消耗的和大于q,那么不可能。
2.考虑如果需要移动气球,那么肯定是在时刻0的时候移动,我们用set维护一个3-element entry记录(当前气球标号,该球消耗的能量,到达0位置所需要的时间),并按最后一项的值从大向小排序。初始化时所有好球消耗的能量为0,时间根据dis/v向上取整。所有坏球计算所需最小的消耗和时间。每次从set中拿出第一位的项(时间最长),因为是它限制了最后到达的时间,给他能量看能否快过第二项,如果在当前能量+之前消耗的 可以保证他快过第二项,那么更新该项并且重新插入,同时更新剩余的能量。如果不能的话则循环结束,将所有的剩余能量尝试更新最开始的项,返回该项所需的时间。
因为每次消耗的q会最少增加1,所以总得复杂度是O(q * m * logn)
#define FOR(a, b, n) for(int (a) = (b); (a) < (n); ++(a))#define ITE(a, v) for(auto (a) = v.begin(); (a) != v.end(); ++(a))#define LL long long#define ALL(v) v.begin(),v.end()#define ZERO(v) memset(v, 0, sizeof v)#define NEG(v) memset(v, -1, sizeof v)#define F first#define S second#define PB push_back#define MP make_pair#define MOD 1000000007#define PI 3.141592653589793inline long double min(long double a , long double b) {if(a < b)return a; return b;}inline long double max(long double a , long double b) {if(a < b)return b; return a;}int m, n;int q;int speed[1100];pair<int,int> pos[110];set<pair<int,int>,greater<pair<int,int> > > uset;int calc(int p, int s){ if(p * s >= 0) return INT_MAX; int t = p / s; if(t * s == p) return abs(t); else return abs(t) + 1;}int solve(){ int sum = 0; int flag[110]; int energy[110]; ZERO(energy); ZERO(flag); FOR(i,0,n) { if(pos[i].first == 0) continue; int p = pos[i].first; int h = pos[i].second; if(speed[h] * p == 0 || speed[h] * p > 0) { flag[i] = 1; } else { int t = p / speed[h]; if(t * speed[h] == p) uset.insert(MP(abs(t),i)); else uset.insert(MP(abs(t) + 1, i)); } } int eng = 0; FOR(i,0,n) { if(!flag[i]) continue; int p = pos[i].first; int h = pos[i].second; int MIN = q + 1; int index = -1; for(int j = 0; j < m; j++) { if(speed[j] * p < 0) { if(abs(j - h) < MIN) { MIN = abs(j - h); index = j; } } } if(index == -1) return -1; int t = p / speed[index]; if(speed[index] * t == p) uset.insert(MP(abs(t), i)); else uset.insert(MP(abs(t) + 1, i)); flag[i] = MIN; energy[i] = MIN; eng += MIN; } if(eng > q) return -1; int remain = q - eng; while(remain > 0) { pair<int,int> slow = *(uset.begin()); uset.erase(uset.begin()); int limit = slow.first; if(uset.size()) limit = uset.begin()->first; int ii = slow.second; int p = pos[ii].first; int h = pos[ii].second; remain += energy[ii]; int index= -1; int MIN = m + 1; int T = -1; for(int i = max(0, h - remain); i <= min(m - 1, h + remain); i++) { int tt = calc(p, speed[i]); if(tt < limit) { if(abs(i - h) < MIN) { MIN = abs(i - h); index = i; T = tt; } } } if(index == -1 || remain < MIN) { uset.insert(slow); break; } energy[ii] = MIN; remain -= MIN; uset.insert(MP(T,ii)); } int ii = uset.begin()->second; int tt = uset.begin()->first; int p = pos[ii].first; int h = pos[ii].second; for(int i = max(0, h - remain); i <= min(m - 1, h + remain); i++) { int t = calc(p, speed[i]); tt = min(tt,t); } return tt;}int main(){ int Tcase; cin >> Tcase; FOR(hh,0,Tcase) { cin >> n >> m >> q; FOR(i,0,m) cin >> speed[i]; FOR(i,0,n) cin >> pos[i].first >> pos[i].second; cout << "Case #" << hh + 1 << ": "; uset.clear(); int res = solve(); if(res != -1) cout << res << endl; else cout << "IMPOSSIBLE" << endl; } return 0;}
Problem C. IP Address Summarization
这题当时卡了挺长时间,题意就是求最小的能表示当前网段的一个集合,因为比如1.0.0.0/9和1.128.0.0/9是可以合写成1.0.0.0/8的。对于斜杠后面的数我称它为掩码最低位。声明32个hashset,对于每个IP,先将其标准化后(和掩码&一下),然后转化为long long(高低位要分清楚,我是按照题意直接记录的,即1.0.0.0为00000001.24个0),因为32位数最高不超过2^32-1。根据掩码最低位的不同insert到不同的hashset里,这样先去重,然后从第32个hashset开始遍历所有的值,如果对第i个hashset的第j个值,设为val,如果val在第i位(从高向低)为1,那么看一下是否val去掉该位的值(val-(1<<(32-i))也在该hashset中,如果在的话就向前一个hashset中插入(val-(1<<(32-i)),当前hashset的不急着删除,反正下一步也会删除掉。
接下来就是去掉重合的subnet,仍旧从第32个hashset开始,对于每一项,如果一个一个去掉2进制中得1之后,所得到的值在之前的某个hashset中出现,则说明前面的subnet可以覆盖当前的,删掉即可。
复杂度为O(32 * 32 * n)
这题本身不难,我写的可能复杂了很多,主要是当时index从0或者从1开始理解起来很混乱,想清楚了以后实现还是很简单,位操作还是能解决很多问题的
#define FOR(a, b, n) for(int (a) = (b); (a) < (n); ++(a))#define ITE(a, v) for(auto (a) = v.begin(); (a) != v.end(); ++(a))#define LL long long#define ALL(v) v.begin(),v.end()#define ZERO(v) memset(v, 0, sizeof v)#define NEG(v) memset(v, -1, sizeof v)#define F first#define S second#define PB push_back#define MP make_pair#define MOD 1000000007#define PI 3.141592653589793inline long double min(long double a , long double b) {if(a < b)return a; return b;}inline long double max(long double a , long double b) {if(a < b)return b; return a;}int n;unordered_set<LL> uset[33];string conv(LL val){ vector<int> res(4); for(int i = 3; i >= 0 ; i--) { res[i] = val % 256; val /= 256; } string r; FOR(i,0,res.size()) { r += to_string(res[i]); r.PB('.'); } r.pop_back(); return r;}vector<int> split(string s){ int pos2 = s.find('.'); int pos1 = 0; vector<string> res; while(pos2 != -1) { res.PB(s.substr(pos1, pos2 - pos1)); pos1 = pos2 + 1; pos2 = s.find('.', pos1 ); } if(pos1 != s.size()) res.PB(s.substr(pos1)); vector<int> ans; FOR(i,0,res.size()) ans.PB(stoi(res[i])); return ans;}void clearPos(LL &val, LL base){ if((val & base) == 0) return; val -= base;}int main(){ int Tcase; cin >> Tcase; FOR(hh,0,Tcase) { FOR(i,0,33) uset[i].clear(); cin >> n; FOR(i,0,n) { string s; cin >> s; int pos = s.find('/'); int val = stoi(s.substr(pos + 1)); vector<int> temp = split(s.substr(0,pos)); LL tmp = 0; LL base = 1; for(int j = 3; j >= 0; j--) { tmp += base * temp[j]; base *= 256; } //cout << conv(tmp) << endl; base = 1LL <<(32 -val); base /= 2; for(int j = val + 1; j <= 32; j++,base /= 2) { clearPos(tmp,base); } uset[val].insert(tmp); } LL base = 1; for(int i = 32; i >= 1; i--, base *= 2) { ITE(j,uset[i]) { LL val = *j; if((val & base) != 0) { LL val2 = val - base; if(uset[i].count(val2) == 1) uset[i- 1].insert(val2); } else { LL val2 = val | base; if(uset[i].count(val2) == 1) uset[i- 1].insert(val); } } } base = 1; for(int i = 32; i >= 1; i--, base *= 2) { vector<LL> E; ITE(j,uset[i]) { LL tmpBase = base; LL val = *j; clearPos(val, tmpBase); tmpBase *= 2; bool flag= false; for(int k = i - 1; k >= 0; k--, tmpBase *= 2) { if(uset[k].count(val) == 1) { flag = true; break; } clearPos(val, tmpBase); } if(flag) E.PB(*j); } FOR(j,0,E.size()) uset[i].erase(E[j]); } set<pair<LL,int> > ans; for(int i = 32; i >= 1; i--, base *= 2) { ITE(j,uset[i]) { ans.insert(MP(*j,i)); } } cout << "Case #" << hh + 1 << ":" << endl; ITE(i,ans) cout << conv(i->first) << "/" << i->second << endl; // cout << solve() << endl; } return 0;}
Problem D. Virtual Rabbit
没做出来,感觉没什么头绪,待我研究了大神的代码以后补上
- Google APAC Round D题解
- Google APAC Test 2017 Round D
- Google APAC Test 2017 Round D
- Google APAC test 2015 Round B Problem D-Parentheses Order
- Google APAC 2016 University Graduates Test Round D解题报告
- Google APAC 2016 University Graduates Test Round D
- Problem D. Soldiers Google APAC 2017 University Test Round C
- Problem A. Vote Google APAC 2017 University Test Round D
- Problem D. gMatrix Google APAC 2016 University Test Round C
- Problem B. gBalloon Google APAC 2016 University Test Round D
- Google APAC 2017 Round E
- Google中国2015校园招聘笔试Round D APAC Test Problem D. Itz Chess
- Problem D. Stretch Rope Google APAC 2017 University Test Round D
- 【在线笔试题解题报告系列】Google APAC 2017 University Test Round A
- 【在线笔试题解题报告系列】Google APAC 2017 University Test Round B
- 【在线笔试题解题报告系列】Google APAC 2017 University Test Round E
- Catalan数和应用 & 2015 google APAC round 2 problem D 括号配对问题
- Google中国2015校园招聘笔试Round D APAC Test Problem A. Cube IV
- 常见数据库使用JDBC连接方式
- Java 枚举知识点
- MVC| Razor 布局-模板页 | ViewStart.cshtml
- (二分图匹配) Matrix
- 机器学习实战-第一章
- Google APAC Round D题解
- Android中layout_gravity和gravity属性的区别
- spring国际化
- 1!+2!+----+100!阶乘求和
- Day 5(11.8):(2)实现完整性
- Wireshark网络分析就这么简单 -- 目录
- UVA 11300Spreading the Wealth
- Swift学习 协议Protocol
- 黑马程序员--集合(二)