题意:给出一个4×4的点阵,连接相邻点可以构成一个九宫格,每个小格边长为1。从没有边的点阵开始,两人轮流向点阵中加边,如果加入的边构成了新的边长为1的小正方形,则加边的人得分。构成几个得几分,最终完成九宫格时,谁的分高谁赢。现在给出两人前若干步的操作,问接下来两人都采取最优策略的情况下,谁赢。

分析:博弈搜索,有人说要加记忆化,我没有加也过了……与赤裸裸的博弈搜索的区别在于对于最终状态,并不是谁无路可走谁输,而是谁分低谁输。注意判断分数相等的情况。在搜索中每个节点要么是必胜态,要么是必败态,可参见这里对NP问题的描述:http://www.cnblogs.com/rainydays/archive/2011/05/27/2059781.html

边的存储与判断不好处理,我是使用了edge_row[ ][ ]数组来存储横向边,edge_col[ ][ ]来存储纵向边。并用其左边(横向)或上边(纵向)的点来代表这条边。

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstring>
  4. using namespace std;
  5.  
  6. struct Point
  7. {
  8. int x, y;
  9. Point()
  10. {}
  11. Point(int x, int y):x(x), y(y)
  12. {}
  13. };
  14.  
  15. bool edge_row[][];
  16. bool edge_col[][];
  17. bool tom_turn;
  18. int edge_num;
  19. int tom_score, jerry_score;
  20.  
  21. Point get_point(int a)
  22. {
  23. return Point((a - ) / , (a - ) % );
  24. }
  25.  
  26. void add_edge(Point a, Point b, bool value)
  27. {
  28. if (a.x > b.x || a.y > b.y)
  29. swap(a, b);
  30. if (a.x == b.x)
  31. edge_row[a.x][a.y] = value;
  32. else
  33. edge_col[a.x][a.y] = value;
  34. }
  35.  
  36. int square(Point a)
  37. {
  38. if (a.x < || a.y < || a.x > || a.y > )
  39. return ;
  40. bool ret = true;
  41. ret = ret && edge_row[a.x][a.y];
  42. ret = ret && edge_col[a.x][a.y];
  43. ret = ret && edge_row[a.x + ][a.y];
  44. ret = ret && edge_col[a.x][a.y + ];
  45. if (ret)
  46. return ;
  47. return ;
  48. }
  49.  
  50. int get_score(Point a, Point b)
  51. {
  52. if (a.x > b.x || a.y > b.y)
  53. swap(a, b);
  54. if (a.x == b.x)
  55. return square(Point(a.x - , a.y)) + square(a);
  56. return square(Point(a.x, a.y - )) + square(a);
  57. }
  58.  
  59. void input()
  60. {
  61. tom_turn = true;
  62. tom_score = jerry_score = ;
  63. scanf("%d", &edge_num);
  64. memset(edge_row, , sizeof(edge_row));
  65. memset(edge_col, , sizeof(edge_col));
  66. for (int i = ; i < edge_num; i++)
  67. {
  68. int a, b;
  69. scanf("%d%d", &a, &b);
  70. Point p1 = get_point(a);
  71. Point p2 = get_point(b);
  72. add_edge(p1, p2, true);
  73. if (tom_turn)
  74. tom_score += get_score(p1, p2);
  75. else
  76. jerry_score += get_score(p1, p2);
  77. tom_turn = !tom_turn;
  78. }
  79. }
  80.  
  81. bool dfs(int next_score, int previous_score, bool tom_turn)
  82. {
  83. bool win = false;
  84. bool did = false;
  85. for (int i = ; i < ; i++)
  86. {
  87. for (int j = ; j < ; j++)
  88. {
  89. if (!edge_row[i][j])
  90. {
  91. did = true;
  92. Point a = Point(i, j);
  93. Point b = Point(i, j + );
  94. add_edge(a, b, true);
  95. int score = get_score(a, b);
  96. win = !dfs(previous_score, next_score + score, !tom_turn);
  97. add_edge(a, b, false);
  98. if (win)
  99. return true;
  100. }
  101. if (!edge_col[j][i])
  102. {
  103. did = true;
  104. Point a = Point(j, i);
  105. Point b = Point(j + , i);
  106. add_edge(a, b, true);
  107. int score = get_score(a, b);
  108. win = !dfs(previous_score, next_score + score, !tom_turn);
  109. add_edge(a, b, false);
  110. if (win)
  111. return true;
  112. }
  113. }
  114. }
  115. if (!did)
  116. {
  117. if (next_score == previous_score)
  118. return !tom_turn;
  119. return next_score > previous_score;
  120. }
  121. return false;
  122. }
  123.  
  124. int main()
  125. {
  126. int case_num;
  127. scanf("%d", &case_num);
  128. for (int i = ; i <= case_num; i++)
  129. {
  130. input();
  131. bool tom_win;
  132. if (tom_turn)
  133. tom_win = dfs(tom_score, jerry_score, tom_turn);
  134. else
  135. tom_win = !dfs(jerry_score, tom_score, !tom_turn);
  136. printf("Case #%d: ", i);
  137. if (tom_win)
  138. printf("Tom200\n");
  139. else
  140. printf("Jerry404\n");
  141. }
  142. return ;
  143. }

2013 ACM/ICPC 南京网络赛F题的更多相关文章

  1. 2013 ACM/ICPC 长春网络赛F题

    题意:两个人轮流说数字,第一个人可以说区间[1~k]中的一个,之后每次每人都可以说一个比前一个人所说数字大一点的数字,相邻两次数字只差在区间[1~k].谁先>=N,谁输.问最后是第一个人赢还是第 ...

  2. 2013 ACM/ICPC 长沙网络赛J题

    题意:一个数列,给出这个数列中的某些位置的数,给出所有相邻的三个数字的和,数列头和尾处给出相邻两个数字的和.有若干次询问,每次问某一位置的数字的最大值. 分析:设数列为a1-an.首先通过相邻三个数字 ...

  3. 2013 ACM/ICPC 长春网络赛E题

    题意:给出一个字符串,要从头.尾和中间找出三个完全相等的子串,这些串覆盖的区间互相不能有重叠部分.头.尾的串即为整个字符串的前缀和后缀.问这个相同的子串的最大长度是多少. 分析:利用KMP算法中的ne ...

  4. 2013 ACM/ICPC 杭州网络赛C题

    题意:驴和老虎,在一个矩阵的两个格子里,有各自的起始方向.两者以相同的速度向前移动,前方不能走时驴总是向右,老虎总是向左.他们不能超出矩阵边界也不能走自己走过的格子(但可以走对方走过的格子).如果不能 ...

  5. 2019 ICPC南京网络赛 F题 Greedy Sequence(贪心+递推)

    计蒜客题目链接:https://nanti.jisuanke.com/t/41303 题目:给你一个序列a,你可以从其中选取元素,构建n个串,每个串的长度为n,构造的si串要满足以下条件, 1. si ...

  6. 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的时候的个数,然后需要预处理下小 ...

  7. 2013 ACM/ICPC 成都网络赛解题报告

    第三题:HDU 4730 We Love MOE Girls 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4730 水题~~~ #include < ...

  8. HDU 4731 Minimum palindrome 2013 ACM/ICPC 成都网络赛

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4731 题解:规律题,我们可以发现当m大于等于3时,abcabcabc……这个串的回文为1,并且字典数最小 ...

  9. hdu 4762 && 2013 ACM/ICPC 长春网络赛解题报告

    这次的答案是猜出来的,如果做得话应该是应该是一个几何概型的数学题: 答案就是:n/(m^(n-1)); 具体的证明过程: 1.首先枚举这M个点中的的两个端点,概率是:n*(n-1); 2.假设这个蛋糕 ...

随机推荐

  1. Java设计模式-桥接模式(Bridge)

    桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化.桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时 ...

  2. Java基础-多线程

    介绍 操作系统能同时运行几个程序,每个独立运行的程序又称之为进程. 对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程.线程提供了多任务处理的能力 用进程和线程的观点来研究软件是当今普遍采 ...

  3. 【poj1745】 Divisibility

    http://poj.org/problem?id=1745 (题目链接) 题意 给出n串数,可以在其两两之间添加+或-,判断是否存在某种方案使得出的表达式的答案可以整除k. Solution 水题一 ...

  4. BZOJ2654 tree

    Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色 ...

  5. Tomcat Server Configuration Automation Reinforcement

    目录 . 引言 . 黑客针对WEB Server会有那些攻击面 . 针对Tomcat Server可以做的安全加固 . Managing Security Realms with JMX . 实现对T ...

  6. input type="submit" 和"button"有什么区别?

    http://www.zhihu.com/question/20839977 在一个页面上画一个按钮,有四种办法: <input type="button" /> 这就 ...

  7. linux c学习笔记----进程创建(fork,wait,waitpid)

    1.pid_t fork(); (1)当一个进程调用了fork 以后,系统会创建一个子进程.这个子进程和父进程不同的地方只有他的进程ID 和父进程ID,其他的都是一样.就象符进程克隆(clone)自己 ...

  8. 将Spark中CompactBuf转换为String

    val rdd = sc.textFile("hdfs://hbase11:9000/sparkTsData/ipsoftware/wincc").map{ line => ...

  9. std::thread join和detach区别

    thread detach, join 线程有两种状态,joinable或者detachable,pthread默认创建的线程是joinable的,也可以指定atrribute创建成一个detacha ...

  10. Redis Cluster 理论知识

    http://www.ttlsa.com/redis/redis-cluster-theoretical-knowledge/ Redis 集群的 TCP 端口(Redis Cluster TCP p ...