UVa 742 Domino Game

发布时间:2026/10/28 1:37:19

UVa 742 Domino Game 题目描述Domino\texttt{Domino}Domino游戏采用282828张多米诺骨牌每张牌的两面分别标有数字000到666。两面数字相同的牌称为双块。游戏由两名玩家Red\texttt{Red}Red和Green\texttt{Green}Green进行双方各获得nnn张牌且牌堆不重复。游戏开始时拥有最大数字双块的玩家先手将该双块放置在桌面中央形成一条链链的两端称为“极端”。此后双方轮流行动每次行动时当前玩家必须从自己剩余的牌中选出一张将其放置在链的某一端使得该牌与极端相邻的那一面的数字与极端数字相同。放置后牌的另一面成为新的极端。若当前玩家没有任何牌能与任一极端匹配则必须跳过该回合。胜利条件率先将自己手中所有牌全部放完的玩家获胜。给定双方的初始牌组需要判断只有Red\texttt{Red}Red可能获胜只有Green\texttt{Green}Green可能获胜双方均可能获胜双方均不可能获胜。本题并非寻找必胜策略而是判断每位玩家是否存在至少一条合法的出牌路径使其最终获胜。输入格式输入包含多个测试用例每个测试用例占一行格式为n r11 r12 r21 r22 ... rn1 rn2 g11 g12 ... gn1 gn2其中nnn1≤n≤141 \le n \le 141≤n≤14表示Red\texttt{Red}Red和Green\texttt{Green}Green各自获得的牌数ri1 ri2r_{i1} \, r_{i2}ri1​ri2​表示Red\texttt{Red}Red的第iii张牌的两个数字gi1 gi2g_{i1} \, g_{i2}gi1​gi2​表示Green\texttt{Green}Green的第iii张牌的两个数字所有牌均不重复至少有一名玩家拥有一张双块每个数字均为000到666的整数。数字之间可由任意数量的空白字符分隔。相邻测试用例之间无空行。输入以一行n0n 0n0结束。输出格式对于每个测试用例输出一行内容为以下四种消息之一Only player Red can winOnly player Green can winBoth players can winNo players can win两个连续测试用例的输出之间用一个空行隔开。样例输入1 6 6 0 0 2 5 5 3 4 1 5 3 5 2 1 1 2 2 3 3 4 4 1 4 5 4 4 0输出Only player Red can win Both players can win No players can win Only player Green can win题目分析游戏的状态由以下要素决定当前链的两个极端数字左端和右端当前轮到哪名玩家行动Red\texttt{Red}Red和Green\texttt{Green}Green各自剩余的牌用位掩码表示共282828张牌。由于n≤14n \le 14n≤14双方总牌数为2n≤282n \le 282n≤28恰好等于全部牌的数量因此每个玩家的剩余牌集合可以表示为一个282828位的二进制掩码。游戏过程是一个确定性的状态转移过程每个状态下当前玩家从自己的剩余牌中枚举所有能与左端或右端匹配的牌放置后产生新状态若没有可用的牌则跳过回合。游戏终止于某玩家手中的牌数为000。我们需要判断的是从初始状态出发是否存在一条状态转移路径使得Red\texttt{Red}Red最终出完所有牌以及是否存在一条路径使得Green\texttt{Green}Green最终出完所有牌。这两者可以独立判断。由于状态空间有限虽然2282^{28}228理论上很大但实际可达状态数受牌数和链形态限制在n≤14n \le 14n≤14时完全可枚举可以使用广度优先搜索BFS\texttt{BFS}BFS遍历所有可达状态分别检查是否能够到达红方或绿方获胜的终止状态。解题思路状态表示将282828张牌分别编号为000到272727并建立数字对到编号的映射。每张牌记录其两个数字无序。定义结构体State\textit{State}State包含left、right当前链两端的数字turn当前行动玩家000表示Red\texttt{Red}Red111表示Green\texttt{Green}GreenmaskR、maskG各自剩余牌的位掩码282828位某位为111表示该牌仍在手中。初始状态首先从双方的牌中找出数字最大的双块。由于题目保证至少有一名玩家拥有双块因此可以唯一确定拥有该双块的玩家若最大双块数字相同则只可能有一张因为牌不重复。该玩家作为先手必须首先放置此双块。放置后链的两端数字均为该双块上的数字且该牌从先手玩家的掩码中移除。当前行动玩家切换为对方。广度优先搜索BFS\texttt{BFS}BFS分别对Red\texttt{Red}Red和Green\texttt{Green}Green作为目标玩家执行一次BFS\texttt{BFS}BFS判断是否存在获胜路径。BFS\texttt{BFS}BFS从初始状态开始用队列扩展所有可达状态。使用哈希集合记录已访问状态避免重复扩展。对于每个出队状态若maskR 0则Red\texttt{Red}Red已出完所有牌此时若目标为Red\texttt{Red}Red则返回true否则继续但若目标为Green\texttt{Green}Green则此状态不是Green\texttt{Green}Green的获胜状态因为Red\texttt{Red}Red先获胜了。若maskG 0同理判断目标是否为Green\texttt{Green}Green。否则根据turn确定当前玩家枚举其手中所有牌遍历282828位掩码。对于每张牌尝试将其放置在左端或右端若匹配生成新状态新链两端数字相应更新该牌从当前玩家的掩码中移除行动玩家切换为对方。若新状态尚未访问则入队。若当前玩家没有任何一张牌能与任一极端匹配则只能跳过回合生成一个turn取反、其余不变的状态若未访问则入队。BFS\texttt{BFS}BFS结束后仍未到达目标玩家的获胜状态则返回false。状态数估计虽然掩码有282828位但实际可达状态远小于2282^{28}228因为双方总牌数固定为2n2n2n链两端的数字受已放置的牌限制状态转移有向且无环牌数持续减少跳过回合不减少牌数但会切换玩家可能形成循环需用哈希去重。对于n≤14n \le 14n≤14实际状态数在可接受范围内BFS\texttt{BFS}BFS能够快速完成。复杂度分析每个状态转移枚举当前玩家的剩余牌最多282828张每张尝试左右两个方向常数小。状态数SSS不超过所有可能的掩码组合与链端组合最坏情况下在n14n14n14时约为O(228)O(2^{28})O(228)但实际远小于此完全可行。总时间复杂度O(S⋅28)O(S \cdot 28)O(S⋅28)空间复杂度O(S)O(S)O(S)。代码实现// Domino Game// UVa ID: 742// Verdict: Accepted// Submission Date: 2026-07-05// UVa Run Time: 0.000s//// 版权所有C2026邱秋。metaphysis # yeah dot net#includebits/stdc.husingnamespacestd;// 28张多米诺牌每张牌两个数字编号0~27intdomino[28][2];intidxMap[7][7];// 游戏状态structState{intleft,right;// 当前链两端数字intturn;// 0: Red, 1: Greenuint32_tmaskR,maskG;// 各自剩余牌的位掩码28位booloperator(constStateother)const{returnleftother.leftrightother.rightturnother.turnmaskRother.maskRmaskGother.maskG;}};// 哈希函数用于unordered_setstructStateHash{size_toperator()(constStates)const{uint64_th1(uint64_t)s.left60|(uint64_t)s.right54|(uint64_t)s.turn53|(uint64_t)s.maskR25|(uint64_t)s.maskG;return(size_t)h1;}};// 判断目标玩家target 0 表示 Red1 表示 Green是否有获胜路径boolcanWin(inttarget,constStateinit){queueStateq;unordered_setState,StateHashvisited;q.push(init);visited.insert(init);while(!q.empty()){State curq.front();q.pop();// 检查是否有人获胜if(cur.maskR0)returntarget0;// Red 出完if(cur.maskG0)returntarget1;// Green 出完uint32_tmask(cur.turn0)?cur.maskR:cur.maskG;boolhasMovefalse;// 枚举当前玩家的每张牌for(intid0;id28;id){if(!(mask(1uid)))continue;intadomino[id][0],bdomino[id][1];// 尝试匹配左端if(acur.left||bcur.left){hasMovetrue;intnewLeft(acur.left)?b:a;intnewRightcur.right;uint32_tnewMaskRcur.maskR,newMaskGcur.maskG;if(cur.turn0)newMaskR~(1uid);elsenewMaskG~(1uid);State nxt{newLeft,newRight,1-cur.turn,newMaskR,newMaskG};if(!visited.count(nxt)){if(nxt.maskR0target0)returntrue;if(nxt.maskG0target1)returntrue;visited.insert(nxt);q.push(nxt);}}// 尝试匹配右端if(acur.right||bcur.right){hasMovetrue;intnewRight(acur.right)?b:a;intnewLeftcur.left;uint32_tnewMaskRcur.maskR,newMaskGcur.maskG;if(cur.turn0)newMaskR~(1uid);elsenewMaskG~(1uid);State nxt{newLeft,newRight,1-cur.turn,newMaskR,newMaskG};if(!visited.count(nxt)){if(nxt.maskR0target0)returntrue;if(nxt.maskG0target1)returntrue;visited.insert(nxt);q.push(nxt);}}}// 当前玩家无牌可出跳过回合if(!hasMove){State nxt{cur.left,cur.right,1-cur.turn,cur.maskR,cur.maskG};if(!visited.count(nxt)){if(nxt.maskR0target0)returntrue;if(nxt.maskG0target1)returntrue;visited.insert(nxt);q.push(nxt);}}}returnfalse;}intmain(){// 初始化所有牌编号0~27intcnt0;for(inta0;a6;a)for(intba;b6;b){domino[cnt][0]a;domino[cnt][1]b;idxMap[a][b]cnt;cnt;}boolneedBlankfalse;intn;while(cinnn!0){uint32_tmaskR0,maskG0;// 读取 Red 的 n 张牌for(inti0;in;i){intx,y;cinxy;if(xy)swap(x,y);intididxMap[x][y];maskR|(1uid);}// 读取 Green 的 n 张牌for(inti0;in;i){intx,y;cinxy;if(xy)swap(x,y);intididxMap[x][y];maskG|(1uid);}// 找出最大双块的持有者intmaxDoubleVal-1,maxDoublePlayer-1,maxDoubleId-1;for(intid0;id28;id){if(domino[id][0]domino[id][1]){intvaldomino[id][0];if(maskR(1uid)||maskG(1uid)){if(valmaxDoubleVal){maxDoubleValval;maxDoublePlayer(maskR(1uid))?0:1;maxDoubleIdid;}}}}// 初始状态最大双块已由先手放下State init;init.leftinit.rightmaxDoubleVal;init.maskRmaskR;init.maskGmaskG;if(maxDoublePlayer0)init.maskR~(1umaxDoubleId);elseinit.maskG~(1umaxDoubleId);init.turn1-maxDoublePlayer;// 轮到对方boolredWincanWin(0,init);boolgreenWincanWin(1,init);if(needBlank)coutendl;needBlanktrue;if(redWingreenWin)coutBoth players can win\n;elseif(redWin!greenWin)coutOnly player Red can win\n;elseif(!redWingreenWin)coutOnly player Green can win\n;elsecoutNo players can win\n;}return0;}总结本题是一道典型的状态空间搜索问题关键点在于将游戏状态精确定义为链两端、当前玩家和双方剩余牌的掩码利用广度优先搜索BFS\texttt{BFS}BFS枚举所有可达状态分别判断两位玩家各自是否存在获胜路径使用哈希集合去重避免状态无限循环位掩码表示牌集合高效进行集合操作。该解法直接且可靠对于n≤14n \le 14n≤14的限制完全满足时间和空间要求。通过分别对两位玩家调用搜索函数可以清晰得到四种可能的结果。
延伸阅读

更多相关文章

2026/10/28 1:32:19

1995-2025年 全球经济自由度指数(xlsx)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 3:02:48

Linux管道进程间通信:从文件描述符到PIPE_BUF的避坑实战

1. 管道凭什么成为进程通信的默认答案写过几年 Linux 下的程序,你会发现一个现象:不管学什么语言、做什么方向,只要涉及到进程间通信,第一个被拿出来讲的永远是管道。很多人把这当成教材的偷懒,其实恰恰相反&#xff0…

2026/10/28 3:02:48

天气识别技术:从图像分类到工程化部署全解析

1. 项目背景与核心目标天气识别作为计算机视觉领域的基础应用场景,其技术实现路径远比表面看起来复杂。这个项目之所以值得深入探讨,是因为它完美融合了图像分类、数据增强、模型轻量化等关键技术点。在实际应用中,从手机相册自动分类到气象观…

2026/10/28 3:02:48

AI自主失控预警与治理:企业技术负责人的应对策略

1. 当AI开始自主行动:企业技术负责人的五个预警信号最近和几位科技公司的技术负责人聊天,发现一个有趣现象:大家不再讨论"如何让AI更好地执行指令",而是开始担忧"AI会不会自己决定做什么"。上周某零售巨头的C…

2026/10/28 3:02:48

Word文档高效定位与智能标注全攻略

1. 为什么我们需要精准定位Word文档内容在日常办公场景中,我们经常需要处理几十页甚至上百页的Word文档。想象一下这样的场景:法务人员需要在200页的合同中快速找到所有"违约责任"条款;编辑需要在一部长篇书稿中标记所有"人物…

2026/10/28 3:02:48

开发 context-mode:用规则引擎实现浏览器场景切换

这个名为 context-mode 的项目,最初源于我自己每天在浏览器里的真实痛点:写代码的时候需要打开 GitHub、Stack Overflow、本地文档;做运营分析的时候要切到数据后台、投放平台、行业资讯站;到了专注写作时,又恨不得把社…

2026/10/28 2:57:47

RAG分块技术:7种策略提升大模型性能

1. RAG分块技术概述:大模型优化的关键一步RAG(Retrieval-Augmented Generation)分块技术正在成为提升大模型性能的核心手段。作为一名长期从事NLP落地的工程师,我发现合理的文本分块策略能直接决定RAG系统的召回精度和生成质量。不…

2026/10/27 14:24:03

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/27 9:34:54

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/27 0:59:21

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/28 0:02:13

Python股票自动交易系统源码解析:从行情获取到风控的完整链路

简介:这份资源是面向高校计算机、金融相关专业毕业设计场景的完整项目源码包,主题为基于Python的股票自动交易系统,适合需要完成毕设选题、课程设计或自学金融量化交易开发的学生与开发者参考。压缩包共收录687个文件,整体约14.93…

2026/10/28 0:02:13

视酷酷信IM源码部署指南:Java 17+MySQL 8.0.33实战配置

简介:这是一套2024年亲测可部署的视酷酷信IM即时通讯系统源码,面向具备Java、OC、C#及Vue开发能力的技术人员,解决私有化即时通讯平台快速搭建与二次定制需求,尤其适用于需集成商城、保障数据主权的中小型企业或独立开发者。资源共…

2026/10/28 0:02:13

Python爬取百度迁徙数据:接口解析、批量采集与避坑指南

简介:这份资源是一个用Python爬取百度迁徙数据的脚本压缩包,面向具备Python基础、希望入门网络爬虫与数据解析的开发者,解决按日期获取全国热门城市人口迁徙数据的问题。包内共1个文件,为单个py脚本,压缩包约1KB&#…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑