2013 ACM/ICPC 南京网络赛F题
题意:给出一个4×4的点阵,连接相邻点可以构成一个九宫格,每个小格边长为1。从没有边的点阵开始,两人轮流向点阵中加边,如果加入的边构成了新的边长为1的小正方形,则加边的人得分。构成几个得几分,最终完成九宫格时,谁的分高谁赢。现在给出两人前若干步的操作,问接下来两人都采取最优策略的情况下,谁赢。
分析:博弈搜索,有人说要加记忆化,我没有加也过了……与赤裸裸的博弈搜索的区别在于对于最终状态,并不是谁无路可走谁输,而是谁分低谁输。注意判断分数相等的情况。在搜索中每个节点要么是必胜态,要么是必败态,可参见这里对NP问题的描述:http://www.cnblogs.com/rainydays/archive/2011/05/27/2059781.html
边的存储与判断不好处理,我是使用了edge_row[ ][ ]数组来存储横向边,edge_col[ ][ ]来存储纵向边。并用其左边(横向)或上边(纵向)的点来代表这条边。
- #include <cstdio>
- #include <algorithm>
- #include <cstring>
- using namespace std;
- struct Point
- {
- int x, y;
- Point()
- {}
- Point(int x, int y):x(x), y(y)
- {}
- };
- bool edge_row[][];
- bool edge_col[][];
- bool tom_turn;
- int edge_num;
- int tom_score, jerry_score;
- Point get_point(int a)
- {
- return Point((a - ) / , (a - ) % );
- }
- void add_edge(Point a, Point b, bool value)
- {
- if (a.x > b.x || a.y > b.y)
- swap(a, b);
- if (a.x == b.x)
- edge_row[a.x][a.y] = value;
- else
- edge_col[a.x][a.y] = value;
- }
- int square(Point a)
- {
- if (a.x < || a.y < || a.x > || a.y > )
- return ;
- bool ret = true;
- ret = ret && edge_row[a.x][a.y];
- ret = ret && edge_col[a.x][a.y];
- ret = ret && edge_row[a.x + ][a.y];
- ret = ret && edge_col[a.x][a.y + ];
- if (ret)
- return ;
- return ;
- }
- int get_score(Point a, Point b)
- {
- if (a.x > b.x || a.y > b.y)
- swap(a, b);
- if (a.x == b.x)
- return square(Point(a.x - , a.y)) + square(a);
- return square(Point(a.x, a.y - )) + square(a);
- }
- void input()
- {
- tom_turn = true;
- tom_score = jerry_score = ;
- scanf("%d", &edge_num);
- memset(edge_row, , sizeof(edge_row));
- memset(edge_col, , sizeof(edge_col));
- for (int i = ; i < edge_num; i++)
- {
- int a, b;
- scanf("%d%d", &a, &b);
- Point p1 = get_point(a);
- Point p2 = get_point(b);
- add_edge(p1, p2, true);
- if (tom_turn)
- tom_score += get_score(p1, p2);
- else
- jerry_score += get_score(p1, p2);
- tom_turn = !tom_turn;
- }
- }
- bool dfs(int next_score, int previous_score, bool tom_turn)
- {
- bool win = false;
- bool did = false;
- for (int i = ; i < ; i++)
- {
- for (int j = ; j < ; j++)
- {
- if (!edge_row[i][j])
- {
- did = true;
- Point a = Point(i, j);
- Point b = Point(i, j + );
- add_edge(a, b, true);
- int score = get_score(a, b);
- win = !dfs(previous_score, next_score + score, !tom_turn);
- add_edge(a, b, false);
- if (win)
- return true;
- }
- if (!edge_col[j][i])
- {
- did = true;
- Point a = Point(j, i);
- Point b = Point(j + , i);
- add_edge(a, b, true);
- int score = get_score(a, b);
- win = !dfs(previous_score, next_score + score, !tom_turn);
- add_edge(a, b, false);
- if (win)
- return true;
- }
- }
- }
- if (!did)
- {
- if (next_score == previous_score)
- return !tom_turn;
- return next_score > previous_score;
- }
- return false;
- }
- int main()
- {
- int case_num;
- scanf("%d", &case_num);
- for (int i = ; i <= case_num; i++)
- {
- input();
- bool tom_win;
- if (tom_turn)
- tom_win = dfs(tom_score, jerry_score, tom_turn);
- else
- tom_win = !dfs(jerry_score, tom_score, !tom_turn);
- printf("Case #%d: ", i);
- if (tom_win)
- printf("Tom200\n");
- else
- printf("Jerry404\n");
- }
- return ;
- }
2013 ACM/ICPC 南京网络赛F题的更多相关文章
- 2013 ACM/ICPC 长春网络赛F题
题意:两个人轮流说数字,第一个人可以说区间[1~k]中的一个,之后每次每人都可以说一个比前一个人所说数字大一点的数字,相邻两次数字只差在区间[1~k].谁先>=N,谁输.问最后是第一个人赢还是第 ...
- 2013 ACM/ICPC 长沙网络赛J题
题意:一个数列,给出这个数列中的某些位置的数,给出所有相邻的三个数字的和,数列头和尾处给出相邻两个数字的和.有若干次询问,每次问某一位置的数字的最大值. 分析:设数列为a1-an.首先通过相邻三个数字 ...
- 2013 ACM/ICPC 长春网络赛E题
题意:给出一个字符串,要从头.尾和中间找出三个完全相等的子串,这些串覆盖的区间互相不能有重叠部分.头.尾的串即为整个字符串的前缀和后缀.问这个相同的子串的最大长度是多少. 分析:利用KMP算法中的ne ...
- 2013 ACM/ICPC 杭州网络赛C题
题意:驴和老虎,在一个矩阵的两个格子里,有各自的起始方向.两者以相同的速度向前移动,前方不能走时驴总是向右,老虎总是向左.他们不能超出矩阵边界也不能走自己走过的格子(但可以走对方走过的格子).如果不能 ...
- 2019 ICPC南京网络赛 F题 Greedy Sequence(贪心+递推)
计蒜客题目链接:https://nanti.jisuanke.com/t/41303 题目:给你一个序列a,你可以从其中选取元素,构建n个串,每个串的长度为n,构造的si串要满足以下条件, 1. si ...
- HDU 4734 F(x) 2013 ACM/ICPC 成都网络赛
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4734 数位DP. 用dp[i][j][k] 表示第i位用j时f(x)=k的时候的个数,然后需要预处理下小 ...
- 2013 ACM/ICPC 成都网络赛解题报告
第三题:HDU 4730 We Love MOE Girls 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4730 水题~~~ #include < ...
- HDU 4731 Minimum palindrome 2013 ACM/ICPC 成都网络赛
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4731 题解:规律题,我们可以发现当m大于等于3时,abcabcabc……这个串的回文为1,并且字典数最小 ...
- hdu 4762 && 2013 ACM/ICPC 长春网络赛解题报告
这次的答案是猜出来的,如果做得话应该是应该是一个几何概型的数学题: 答案就是:n/(m^(n-1)); 具体的证明过程: 1.首先枚举这M个点中的的两个端点,概率是:n*(n-1); 2.假设这个蛋糕 ...
随机推荐
- Java设计模式-桥接模式(Bridge)
桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化.桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时 ...
- Java基础-多线程
介绍 操作系统能同时运行几个程序,每个独立运行的程序又称之为进程. 对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程.线程提供了多任务处理的能力 用进程和线程的观点来研究软件是当今普遍采 ...
- 【poj1745】 Divisibility
http://poj.org/problem?id=1745 (题目链接) 题意 给出n串数,可以在其两两之间添加+或-,判断是否存在某种方案使得出的表达式的答案可以整除k. Solution 水题一 ...
- BZOJ2654 tree
Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色 ...
- Tomcat Server Configuration Automation Reinforcement
目录 . 引言 . 黑客针对WEB Server会有那些攻击面 . 针对Tomcat Server可以做的安全加固 . Managing Security Realms with JMX . 实现对T ...
- input type="submit" 和"button"有什么区别?
http://www.zhihu.com/question/20839977 在一个页面上画一个按钮,有四种办法: <input type="button" /> 这就 ...
- linux c学习笔记----进程创建(fork,wait,waitpid)
1.pid_t fork(); (1)当一个进程调用了fork 以后,系统会创建一个子进程.这个子进程和父进程不同的地方只有他的进程ID 和父进程ID,其他的都是一样.就象符进程克隆(clone)自己 ...
- 将Spark中CompactBuf转换为String
val rdd = sc.textFile("hdfs://hbase11:9000/sparkTsData/ipsoftware/wincc").map{ line => ...
- std::thread join和detach区别
thread detach, join 线程有两种状态,joinable或者detachable,pthread默认创建的线程是joinable的,也可以指定atrribute创建成一个detacha ...
- Redis Cluster 理论知识
http://www.ttlsa.com/redis/redis-cluster-theoretical-knowledge/ Redis 集群的 TCP 端口(Redis Cluster TCP p ...