日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

谷歌中国算法比赛解题报告 APAC2017C

發(fā)布時間:2023/12/14 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 谷歌中国算法比赛解题报告 APAC2017C 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Problem A.?Monster Path

Problem B.?Safe Squares

Problem C.?Evaluation

Problem D.?Soldiers


終于快寫完了,lz也越來越懶。。。

考試的時候lz異想天開用python刷題……結(jié)果你懂的……lz的python畢竟也不熟練

這題前三題不說了(好吧我沒做),說說第四題


這題很難,如果用標(biāo)準(zhǔn)的博弈思想,算法復(fù)雜度是O(n4),大數(shù)據(jù)托托超時

但是這題可以優(yōu)化,優(yōu)化后能達(dá)到O(n2)!!!

首先分析一下標(biāo)準(zhǔn)做法,DFS, 哪怕我們記錄每一步的結(jié)果,我們還是找了太多的無效節(jié)點(diǎn),要知道要判斷這個點(diǎn)能不能贏,我們要判斷以這個點(diǎn)為起點(diǎn)的所有情況中,有沒有一個對方的失敗點(diǎn),而這情況太多了

但是這題可以倒過來找,跟APAC2015有一道addtion很像,倒著找,所有無效的節(jié)點(diǎn)都不用管了!!!


首先,A,D都取最大值一定是一個勝點(diǎn),如果這個點(diǎn)存在卡牌,直接返回勝利

如果不存在,則橫著掃描,所有A,其它D,都是負(fù)點(diǎn),因?yàn)楣魹镈的卡牌必然有,如果我選了A,其它D,那么你可以選任意A,D這張卡

同理,豎著掃,所有 其它A,D都是負(fù)點(diǎn)

然后掃到第二行第二列的點(diǎn),這個點(diǎn)的正上方的列點(diǎn)如果都是負(fù)點(diǎn),并且這個點(diǎn)的正左方的點(diǎn)如果都是負(fù)點(diǎn),這個點(diǎn)就是勝點(diǎn),然后這個點(diǎn)正右方,正下方就都變成負(fù)點(diǎn),如果這個點(diǎn)上方或左方有勝點(diǎn),那么它就是負(fù)點(diǎn)

對于勝點(diǎn),查看能不能選到,選到就返回,

否則,繼續(xù)往后掃,如果掃的點(diǎn)已經(jīng)處理過,就跳過

這樣是O(n3) 但其實(shí)我們對每個點(diǎn),只要查上方一個點(diǎn)和左方一個點(diǎn)就好,具體原因,自己想……

這樣就是O(n2)

說的不是很清楚(lz承諾……要是過了E,你懂的……),具體怎么搞,請看代碼……

#include <stdio.h> #include <iostream> #include <fstream> #include <math.h> #include <algorithm> #include <vector> #include <set> #include <map> #include <hash_map> #include <hash_set> #include <unordered_map> #include <unordered_set> #include <string.h> #include <queue> #include <list>using namespace std;#define real long long//DFS 做法,耗時n4 class CD { public:CD(){}int M, N;map<int, set<int>> amap;map<int, set<int>> dmap;map<int, map<int,int>> winMap;int checkWinLose(int a, int d){map<int, map<int, int>>::iterator it1;map<int, int>::iterator it2;it1 = winMap.find(a);if (it1 != winMap.end()){it2 = it1->second.find(d);if (it2 != it1->second.end()){return it2->second;}}return 0;}void setWinPoint(int a, int d,int sign=1){winMap[a][d] = sign;map<int, set<int>>::iterator iter, iter2;if (*(dmap[d].begin()) < a){for (iter = dmap.begin(); iter != dmap.end() && iter->first < d; iter++){winMap[a][iter->first] = -sign;}}if (*(amap[a].begin()) < d){for (iter = amap.begin(); iter != amap.end() && iter->first < a; iter++){winMap[iter->first][d] = -sign;}}}bool DFS(int a, int d){map<int, set<int>>::iterator iter, iter2;iter = amap.end();iter--;for (; iter != amap.end()&&iter->first>a;iter--){set<int>::iterator siter;for (siter = iter->second.begin(); siter != iter->second.end();siter++){int na, nd;na = iter->first;nd = max(*siter, d);int k = checkWinLose(na,nd);if (k == -1){setWinPoint(a, d);return true;}else if (k == 1){continue;}else{bool r=DFS(na, nd);if (r){continue;}else{setWinPoint(a, d);return true;}}}}//same as aiter = dmap.end();iter--;for (; iter != dmap.end() && iter->first>d; iter--){set<int>::iterator siter;for (siter = iter->second.begin(); siter != iter->second.end();siter++){int na, nd;na = max(*siter,a);nd = iter->first;int k = checkWinLose(na, nd);if (k == -1){setWinPoint(a, d);return true;}else if (k == 1){continue;}else{bool r = DFS(na, nd);if (r){continue;}else{setWinPoint(a, d);return true;}}}}setWinPoint(a, d, -1);return false;}string SingleProcess(){amap[0].insert(0);dmap[0].insert(0);setWinPoint(amap.rbegin()->first, dmap.rbegin()->first,-1);if (DFS(0, 0)){return "YES";}return "NO";}void run(){FILE* fp = freopen("in.txt", "r", stdin);ofstream fout("out.txt");int Cases = 0;scanf("%d", &Cases);for (int time = 0; time < Cases; time++){scanf("%d", &N);int A, D;amap.clear();dmap.clear();winMap.clear();for (int i = 0; i < N; i++){scanf("%d %d", &A, &D);amap[A].insert(D);dmap[D].insert(A);}fout << "Case #" << (time + 1) << ": " << SingleProcess().c_str() << endl;std::cout << time << endl;}fclose(fp);fout.close();} };//濃縮后倒著推,找到一個就返回,最大耗時n2,但condense比較耗時,關(guān)鍵點(diǎn),找一個點(diǎn)是不是勝點(diǎn)只要考慮該行該列(再優(yōu)化到只考慮比它大一的行列),而DFS要找的是比自身大的所有行所有列。如果不condense,向上移動的操作比較麻煩。 class CX1 { public:CX1(){}int M, N;int MA, MD;struct INT2{int x, y;INT2(){ x = y = 0; }};map<int,int> amap;map<int,int> dmap;vector<int> cmin;vector<int> rmin;vector<INT2> solders;vector<vector<bool>> matrix;vector<vector<int>> winMap;string SingleProcess(){for (int r = MA - 1; r > 0;r--){for (int c = MD - 1; c > 0; c--){if (winMap[r][c] != 0) continue;bool findone = false;if(r+1 < MA){if (winMap[r+1][c] == -1 && c>rmin[r+1]){findone = true;for (int j = r; j > 0; j--) winMap[j][c] = 1;}}if (!findone&&c+1<MD){if (winMap[r][c+1] == -1 && r>cmin[c+1]){findone = true;for (int j = c; j > 0; j--) winMap[r][j] = 1;}}if (!findone){winMap[r][c] = -1;if (matrix[r][c]) return "YES";}}}return "NO";}void run(){FILE* fp = freopen("in.txt", "r", stdin);ofstream fout("out.txt");int Cases = 0;scanf("%d", &Cases);for (int time = 0; time < Cases; time++){scanf("%d", &N);amap.clear();dmap.clear();solders.clear();cmin.clear();rmin.clear();solders.resize(N, INT2());winMap.clear();for (int i = 0; i < N; i++){scanf("%d %d", &solders[i].x, &solders[i].y);amap[solders[i].x] = 0;dmap[solders[i].y] = 0;}MA = MD = 1;for (map<int, int>::iterator iter = amap.begin(); iter != amap.end(); iter++){iter->second = MA++;}for (map<int, int>::iterator iter = dmap.begin(); iter != dmap.end(); iter++){iter->second = MD++;}matrix.clear();matrix.resize(MA, vector<bool>(MD,false));winMap.clear();winMap.resize(MA, vector<int>(MD, 0));cmin.resize(MD, INT_MAX);rmin.resize(MA, INT_MAX);for (int i = 0; i < solders.size(); i++){int t1 = amap[solders[i].x];int t2 = dmap[solders[i].y];matrix[t1][t2] = true;cmin[t2] = min(cmin[t2], t1);rmin[t1] = min(rmin[t1], t2);}fout << "Case #" << (time + 1) << ": " << SingleProcess().c_str() << endl;std::cout << time << endl;}fclose(fp);fout.close();} };//不condense,充分使用map,但利用了題目中10000*10000的數(shù)組,否則只能condense //紅黑樹做索引,vector做存儲matrix,利用10000*10000,效率很高!!! class CX2 { public:CX2(){}int M, N;int MA, MD;struct INT2{int x, y;INT2(){ x = y = 0; }};map<int, set<int>> amap;map<int, set<int>> dmap;//map<int, map<int, int>> winMap; //紅黑樹不能處理,速度太慢而且內(nèi)存占用非常高//unordered_map<int, unordered_map<int, int>> winMap; //hash表的速度依然慢到爆表,而且內(nèi)存占用非常高,和紅黑樹差不多vector<vector<int>> winMap; //vector可以處理,綜合速度比condense慢一些,但不太大,畢竟10000*10000和4000*4000的區(qū)別,內(nèi)存上差很多string SingleProcess(){map<int, set<int>>::iterator aiter, diter,t1,t2;set<int>::iterator siter;map<int, int> temp;for (aiter = amap.end(), aiter--; aiter != amap.end(); aiter--){for (diter = dmap.end(), diter--; diter != dmap.end(); diter--){if (winMap[aiter->first][diter->first]!=0) continue;//這個winMap必然要填滿,所以就這么寫了bool findone = false;t1 = aiter;t1++;if (t1 != amap.end() && winMap[t1->first][diter->first] == -1 && diter->first>*(t1->second.begin())){findone = true;for (t1 = aiter; t1 != amap.end(); t1--) winMap[t1->first][diter->first] = 1;}t1 = diter;t1++;if (!findone&&t1!=dmap.end()&&winMap[aiter->first][t1->first]==-1&&aiter->first>*(t1->second.begin())){findone = true;for (t1 = diter; t1 != dmap.end(); t1--) winMap[aiter->first][t1->first] = 1;}if (!findone){winMap[aiter->first][diter->first] = -1;if (amap[aiter->first].find(diter->first)!=amap[aiter->first].end()) return "YES";}}}return "NO";}void run(){FILE* fp = freopen("in.txt", "r", stdin);ofstream fout("out.txt");int Cases = 0;scanf("%d", &Cases);for (int time = 0; time < Cases; time++){scanf("%d", &N);amap.clear();dmap.clear();winMap.clear();winMap.resize(10001, vector<int>(10001,0));int A, D;for (int i = 0; i < N; i++){scanf("%d %d", &A,&D);amap[A].insert(D);dmap[D].insert(A);}fout << "Case #" << (time + 1) << ": " << SingleProcess().c_str() << endl;std::cout << time << endl;}fclose(fp);fout.close();} };int main() {//CA p;//CB p;//CC p;CX2 p;p.run();return 0; }

總結(jié)

以上是生活随笔為你收集整理的谷歌中国算法比赛解题报告 APAC2017C的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。