Problem A. Monster Path

Problem B. Safe Squares

Problem C. Evaluation

Problem D. Soldiers


终于快写完了,lz也越来越懒。。。

考试的时候lz异想天开用python刷题……结果你懂的……lz的python毕竟也不熟练

这题前三题不说了(好吧我没做),说说第四题


这题很难,如果用标准的博弈思想,算法复杂度是O(n4),大数据托托超时

但是这题可以优化,优化后能达到O(n2)!!!

首先分析一下标准做法,DFS, 哪怕我们记录每一步的结果,我们还是找了太多的无效节点,要知道要判断这个点能不能赢,我们要判断以这个点为起点的所有情况中,有没有一个对方的失败点,而这情况太多了

但是这题可以倒过来找,跟APAC2015有一道addtion很像,倒着找,所有无效的节点都不用管了!!!


首先,A,D都取最大值一定是一个胜点,如果这个点存在卡牌,直接返回胜利

如果不存在,则横着扫描,所有A,其它D,都是负点,因为攻击为D的卡牌必然有,如果我选了A,其它D,那么你可以选任意A,D这张卡

同理,竖着扫,所有 其它A,D都是负点

然后扫到第二行第二列的点,这个点的正上方的列点如果都是负点,并且这个点的正左方的点如果都是负点,这个点就是胜点,然后这个点正右方,正下方就都变成负点,如果这个点上方或左方有胜点,那么它就是负点

对于胜点,查看能不能选到,选到就返回,

否则,继续往后扫,如果扫的点已经处理过,就跳过

这样是O(n3) 但其实我们对每个点,只要查上方一个点和左方一个点就好,具体原因,自己想……

这样就是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比较耗时,关键点,找一个点是不是胜点只要考虑该行该列(再优化到只考虑比它大一的行列),而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的数组,否则只能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;  //红黑树不能处理,速度太慢而且内存占用非常高//unordered_map<int, unordered_map<int, int>> winMap;  //hash表的速度依然慢到爆表,而且内存占用非常高,和红黑树差不多vector<vector<int>> winMap; //vector可以处理,综合速度比condense慢一些,但不太大,毕竟10000*10000和4000*4000的区别,内存上差很多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;
}

谷歌中国算法比赛解题报告 APAC2017C相关推荐

  1. 谷歌中国算法比赛解题报告 APAC2015C

    Problem A. Minesweeper Problem B. Taking Metro Problem C. Broken Calculator Problem D. Tetris 这次的题侧重 ...

  2. [180609] A fumble fish week(BISTU第九届C语言基本技能比赛 解题报告)

    比赛链接:http://acm.bistu.edu.cn/acmhome/contest.do?&method=contestDetail&contestId=66 (外网可能上不去) ...

  3. 7.9模拟比赛解题报告

    7.9模拟比赛 注:本场考试3道题,时间3个小时.全部为codevs上的题目 1.2124 美丽的大树 题目描述 Description 平江路是苏州最美丽的道路,路中间的绿化带上种了两行漂亮的大树, ...

  4. 2014 ACM/ICPC 北京赛区网络赛解题报告汇总

    首页 算法竞赛» 信息聚合 ONLINE JUDGE 书刊杂志 BLOG» 新闻故事» 招聘信息» 投稿须知 2014 ACM/ICPC 北京赛区网络赛解题报告汇总 九月 21st, 2014 | P ...

  5. 【解题报告】2021牛客寒假算法基础集训营4

    [解题报告]2021牛客寒假算法基础集训营4 前面的话 A :九峰与签到题 | 模拟 (签到题) B: 武辰延的字符串 | exKMP D :温澈滢的狗狗 | 二分 E: 九峰与子序列 | d p d ...

  6. 程序设计算法竞赛基础——练习2解题报告

    程序设计算法竞赛基础--练习2解题报告 1001 sort Problem Description 给你n个整数,请按从大到小的顺序输出其中前m大的数. Input 每组测试数据有两行,第一行有两个数 ...

  7. Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)

    http://blog.csdn.net/geniusluzh/article/details/6619575 在说Tarjan算法解决桥和边双连通分量问题之前我们先来回顾一下Tarjan算法是如何求 ...

  8. 程序设计算法竞赛高级——练习1解题报告

    程序设计算法竞赛高级--练习1解题报告 1001 寒冰王座 Problem Description 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的 ...

  9. 7月算法训练------第十四天(栈)解题报告

    7月算法训练------第十四天(栈)解题报告 题目类型:栈 题目难度:简单 第一题.1614. 括号的最大嵌套深度 题目链接:1614. 括号的最大嵌套深度 思路分析: 遍历整个字符串,如果是'(' ...

  10. 2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案

    2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案 1.题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. ...

最新文章

  1. 告别低分辨率网络,微软提出高分辨率深度神经网络HRNet | CVPR 2019
  2. python与人工智能编程-最适合人工智能开发的5种编程语言,Python排第一
  3. HAProxy http和https都使用mode tcp模式
  4. C++编译-链接错误集合
  5. Alpha冲刺第二天
  6. java中的Volatile 变量
  7. 我们采访了小鹏G3「高温抑菌」项目负责人,发现智能车OTA并不简单
  8. QuantLib 101之Swap
  9. Windows 8功能预测
  10. 如何保证API接口数据安全?
  11. appium+python的APP自动化(1)
  12. 虚拟化是什么,虚拟化技术分类
  13. Macbook怎么录屏?macbook怎么屏幕录制
  14. 鸿蒙西游安卓版,鸿蒙西游安卓版_鸿蒙西游V1.0.0_游戏堡
  15. linux 命令运行kodi,在Ubuntu/Debian/Raspbian中安装Kodi for Linux的方法
  16. 蓝桥杯复数运算python
  17. 华为交换机端口安全配置
  18. SQL中日期函数的运用
  19. 工厂(Factory)模式
  20. 马云厌恶美国 阿里巴巴转道香港上市

热门文章

  1. 信息系统分析与设计相关
  2. Word Clock数字时钟动态屏保,让你的电脑锁屏瞬间科技感十足!
  3. 用vb编写一个简易的编译器界面
  4. 羲云社区团购微信小程序多门店版,首页开发
  5. 【STM32】STM32CubeMX使用FreeRTOS教程1----定时器学习
  6. linux vi 字符串替换
  7. 红帽Linux登录密码忘了,redhat linux忘记登陆密码之解决办法
  8. python超市管理系统实训报告_java超市管理系统实训报告
  9. java ut_【JAVA UT】2、写UT的科学步骤
  10. DMX协议和RDM协议