今天比赛又是做得好水的。被狂虐啊。

比赛两个多小时一直没出题,遒遒最先交的若干发都wa了。T_T

我独自在一遍苦思了1006这个题,还好最后把这个题目A掉了,不然又是深坑队友。

题目的意思我就不多说了,直接去hdu上看题意,题意很容易懂。

这里说一下我的解题思路吧。

首先题目总共有24条边这是不会变得,但是每次刚开始的一些条件是作为已知条件给你的,所以你不用考虑读数时候游戏者的智商问题。

对于已知的步奏,我们只要模拟,并且记录两个人的得分就可以了。

关键是后面怎么去处理呢?

其实这个题目有一个关键的条件,虽然总边数有24,但是未知的边数只有12,12是个很小的数字,于是总共可能的状态数只有2^12个,可以用状态压缩dp搞定啦。

但是这个题目还涉及到一些博弈论的知识,简单的说一下吧!

首先说明两个名词,必胜态和必败态。顾名思义,名词我就不解释了。

接下来就是怎么判断一个状态是否必胜态或者必败态。(会不会有中间态?显然不会,不解释)

当前状态是必胜态,当且仅当存在它的某一个下一步状态为必败态;当前状态是必败态,当且仅当它的所有的下一步状态全部都是必胜态。

好好理解上一步这句话。

这个题目需要我们记录的可不仅仅是必胜还是必败,还要我们每个状态记录到底是胜了多少分还是败了多少分?有了这里我们就可以dp了。

我们用一个数组(我在代码中用的是ans1[x])来记录x状态先手的人以最优策略能够胜对方多少分。

用二进制(最多12个0)表示初始状态,即所有的地方都没有填成实线。

显然最终的状态(也就是全部为1的时候,111111……)其所对应的ans1的值为0,因为可以理解为最终都取完了,两个人都不取了,所以差值为0,

于是我们倒推,从1多的数推向1少的数,最终算出0,也就是当前这个人以最优策略能够胜对方多少分!(不用记录每个人的得分,因为得分高并比一定是最优解)

下面我稍微指出来题目的几个小坑吧,都是泪堆出来的惨痛教训!

1.前一段读数的时候要把放过的边全部存起来,同时还要统计两个人的分别得分。

2.虽然游戏从一开始的时候是Tom200开始填充实线的,但是如果读数的时候n为奇数说明dp的时候是Jerry404第一个开始填充的(这里特别要注意)

3.这也不算是坑吧,就是要建立起两点与边的对应关系,同时还要给边编号,dp的每一位是表示的边的状态,不是点哦。

下面上我的代码(巨挫),比赛的时候写的,很难看,请谅解。(中间有两个函数功能其实是一样的,是我写挫了)

如果觉得太难看,我觉得我上面讲得已经十分明白了,自己直接写吧。我的太难看了。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. int f1[],f2[],a[][],p[],q[],t,n,x,y,ans[],ans1[],ans2[];
  6. void codeit()
  7. {
  8. int N=;
  9. for (int i=; i<; i++)
  10. {
  11. if (i%==) continue;
  12. a[i][i+]=++N;
  13. }
  14. for (int i=; i<=; i++) a[i][i+]=++N;
  15. f1[]=,f1[]=,f1[]=;
  16. f1[]=,f1[]=,f1[]=;
  17. f1[]=,f1[]=,f1[]=;
  18. for (int i=; i<=; i++) f1[f1[i]]=i;
  19. }
  20. void add(int& ANS,int now)
  21. {
  22. int pp[],pre=;
  23. memset(pp,-,sizeof pp);
  24. for (int i=; i<=; i++) pp[i]=p[i];
  25. if (now<=)
  26. {
  27. if (now>=)
  28. {
  29. now-=;
  30. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now]==) pre++;
  31. }
  32. else
  33. {
  34. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
  35. if (now>)
  36. {
  37. now-=;
  38. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now]==) pre++;
  39. }
  40. }
  41. }
  42. else
  43. {
  44. if (now%==)
  45. {
  46. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
  47. }
  48. else
  49. {
  50. if (now%!=)
  51. {
  52. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
  53. }
  54. now--;
  55. if (pp[now]== && pp[f1[now]]== && pp[f1[now]+]==) pre++;
  56. }
  57. }
  58. ANS+=pre;
  59. }
  60. int count(int cur,int now)//在cur的状态下加入第now条边
  61. {
  62. //cout<<"now add: "<<cur<<' '<<now<<endl;
  63. int pp[],pre=;
  64. memset(pp,-,sizeof pp);
  65. for (int i=; i<=; i++) if (p[i]==) pp[i]=;
  66. for (int i=; i<=n; i++) { if ((cur&(<<(i-)))) pp[q[i]]=; /*cout<<q[i]<<" q[i] \n";*/ }
  67. //for (int i=1; i<=24; i++) if (pp[i]==0) cout<<i<<' '; else cout<<0<<' '; cout<<endl;
  68. now=q[now]; //cout<<"adding : "<<now<<endl;
  69. if (now<=)
  70. {
  71. if (now>=)
  72. {
  73. now-=;
  74. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now]==) pre++;
  75. }
  76. else
  77. {
  78. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
  79. if (now>)
  80. {
  81. now-=;
  82. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now]==) pre++;
  83. }
  84. }
  85. }
  86. else
  87. {
  88. if (now%==)
  89. {
  90. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
  91. }
  92. else
  93. {
  94. if (now%!=)
  95. {
  96. if (pp[f1[now]]== && pp[f1[now]+]== && pp[now+]==) pre++;
  97. }
  98. now--;
  99. if (pp[now]== && pp[f1[now]]== && pp[f1[now]+]==) pre++;
  100. }
  101. }
  102. return pre;
  103. }
  104. int main()
  105. {
  106. int cas=;
  107. codeit();
  108. scanf("%d",&t);
  109. while (t--)
  110. {
  111. int tot,tep;
  112. memset(p,-,sizeof p);
  113. memset(ans,,sizeof ans);
  114. memset(q,,sizeof q);
  115. scanf("%d",&n);
  116. for (int i=; i<=n; i++)
  117. {
  118. scanf("%d%d",&x,&y);
  119. if (x>y) swap(x,y);
  120. add(ans[i%],a[x][y]);
  121. p[a[x][y]]=;
  122. }
  123. int N=;
  124. for (int i=; i<=; i++)
  125. {
  126. if (p[i]==-) q[++N]=i;
  127. }
  128. /*for (int i=1; i<=24; i++)
  129. if (q[i]>0) cout<<i<<" : "<<q[i]<<endl; cout<<"q[i] \n";*/
  130. n=-n;
  131. tot=(<<n)-;
  132. for (int i=; i<tot; i++) ans1[i]=-;
  133. ans1[tot]=;
  134. for (int i=tot; i>=; i--)
  135. {
  136. for (int j=; j<=n; j++)
  137. {
  138. if ((i&(<<(j-)))==)
  139. {
  140. tep=count(i,j);
  141. int next=i|(<<(j-));
  142. if (tep-ans1[next]>ans1[i]) ans1[i]=tep-ans1[next];
  143. }
  144. }
  145. }
  146. /*for (int i=1; i<=10; i++) cout<<ans1[i]<<' '; cout<<endl;*/
  147. if (n%==) ans1[]=-ans1[];
  148. if (ans[]+ans1[]>ans[]) printf("Case #%d: Tom200\n",++cas);
  149. else printf("Case #%d: Jerry404\n",++cas);
  150. }
  151. return;
  152. }

HDU4753 Fishhead’s Little Game——2013 ACM/ICPC Asia Regional Nanjing Online的更多相关文章

  1. HDU 4749 Parade Show 2013 ACM/ICPC Asia Regional Nanjing Online

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4749 题目大意:给一个原序列N,再给出一个序列M,问从N中一共可以找出多少个长度为m的序列,序列中的数 ...

  2. [2013 ACM/ICPC Asia Regional Nanjing Online C][hdu 4750]Count The Pairs(kruskal + 二分)

    http://acm.hdu.edu.cn/showproblem.php?pid=4750 题意: 定义f(u,v)为u到v每条路径上的最大边的最小值..现在有一些询问..问f(u,v)>=t ...

  3. HDU 4751 Divide Groups 2013 ACM/ICPC Asia Regional Nanjing Online

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4751 题目大意:判断一堆人能否分成两组,组内人都互相认识. 解题思路:如果两个人不是相互认识,该两人之 ...

  4. hdu 4751 Divide Groups bfs (2013 ACM/ICPC Asia Regional Nanjing Online 1004)

    SDUST的训练赛 当时死磕这个水题3个小时,也无心去搞其他的 按照题意,转换成无向图,预处理去掉单向的边,然后判断剩下的图能否构成两个无向完全图(ps一个完全图也行或是一个完全图+一个孤点) 代码是 ...

  5. HDU 4758——Walk Through Squares——2013 ACM/ICPC Asia Regional Nanjing Online

    与其说这是一次重温AC自动机+dp,倒不如说这是个坑,而且把队友给深坑了. 这个题目都没A得出来,我只觉得我以前的AC自动机的题目都白刷了——深坑啊. 题目的意思是给你两个串,每个串只含有R或者D,要 ...

  6. HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)

    Problem Description   Zero and One are good friends who always have fun with each other. This time, ...

  7. hduoj 4710 Balls Rearrangement 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4710 Balls Rearrangement Time Limit: 6000/3000 MS (Java/Ot ...

  8. hduoj 4708 Rotation Lock Puzzle 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4708 Rotation Lock Puzzle Time Limit: 2000/1000 MS (Java/O ...

  9. hduoj 4715 Difference Between Primes 2013 ACM/ICPC Asia Regional Online —— Warmup

    http://acm.hdu.edu.cn/showproblem.php?pid=4715 Difference Between Primes Time Limit: 2000/1000 MS (J ...

随机推荐

  1. java开发划分级别的标准

    一.史诗序: java开发也有一段时间了,整天茫茫碌碌,除了偶尔的小有成就感,剩下的大部分好像都在重复,你是否也遇到了这样的情况? 遇到一个小细节问题,之前不久解决过,现在却是什么都记不起来了 面对每 ...

  2. OpenCV人脸识别的原理 .

    OpenCV人脸识别的原理 . 在之前讲到的人脸测试后,提取出人脸来,并且保存下来,以供训练或识别是用,提取人脸的代码如下: void GetImageRect(IplImage* orgImage, ...

  3. bzoj1854 [Scoi2010]游戏 ([SCOI2010]连续攻击游戏)

    bzoj1854 [Scoi2010]游戏 ([SCOI2010]连续攻击游戏) 据说正解是并查集???我不会 这不是一道匈♂牙利好题吗??? 一个装备的两个属性都向它连边,然后跑一遍匈♂牙利 注意: ...

  4. 【MYSQL命令】查看日志是否开启及日志过期天数

    show variables like 'log_%';show variables like '%expire_logs_days%'

  5. 常用常忘的delegate,记一下。

    多线程: 1 new Thread(new ThreadStart(Method1))).Start(); 1 new Thread(new ParameterizedThreadStart(Meth ...

  6. hdu2065"红色病毒"问题(指数母函数+快速幂取模)

    "红色病毒"问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  7. JAVA基础学习之路(十一)引用传递

    引用传递: 不同栈内存可以指向同一块堆内存,不同栈内存可以对一块堆内存进行修改 范例一: class Message { private int num = 10; public Message(in ...

  8. 算法笔记(c++)--求一个数的所有质数因子

    算法笔记(c++)--求一个数的所有质数因子 先贴题目: 这题不难,恶心在理解上面.最后看评论知道了怎么回事: 2*2*3*3*5=180 按照这逻辑的话应该输入的数由一系列质数相乘出来,所以每次找到 ...

  9. redis利用key计时与计数

    计时 Setex 命令为指定的 key 设置值及其过期时间.如果 key 已经存在, SETEX 命令将会替换旧的值 基本命令: redis 127.0.0.1:6379> SETEX KEY_ ...

  10. 带你玩转JavaScript中的隐式强制类型转换

    正题开始前我想先抛出一个问题,==和===有什么区别?可能一般人会想,不就是后者除了比较值相等之外还会比较类型是否相等嘛,有什么好问的,谁不知道?!但是这样说还不够准确,两者的真正区别其实是==在比较 ...