news 2026/1/30 6:31:06

UVa 10838 The Pawn Chess

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 10838 The Pawn Chess

题目翻译

考虑以下简化版国际象棋:我们有一个4×44 \times 44×4的棋盘,第一行(输入中的最下方)有四个白兵,最后一行(输入中的最上方)有四个黑兵。游戏的目标是让自己的一个兵走到对方底线(白方走到最后一行,黑方走到第一行),或者逼对手无棋可走(即“困毙”)。当轮到某玩家走棋时,若他没有合法走法(包括所有兵已被吃光),则他被困毙。

兵的走法与普通国际象棋相同,但不能一次走两步。即:

  • 兵可以向前(朝向对方底线)走一步,前提是目标格为空。
  • 兵也可以吃掉对方兵,如果对方兵位于其左前方或右前方(斜前方一格)。被吃的兵从棋盘移除。

给定棋盘上兵的位置,假设双方都采取最优策略,判断谁会获胜。同时需要计算游戏结束前会进行的步数(假设获胜方会尽快获胜,输的一方会尽可能拖延)。输入局面总是轮到白方走子。

输入格式

第一行输入测试用例数(最多505050个)。每个用例包含四行描述棋盘,前面有一个空行。四行中的第一行表示棋盘的最后一行(黑兵的起始位置)。黑兵用p表示,白兵用P表示,空位用.表示。每方有111444个兵。初始局面不会是终局局面,且白方至少有一个合法走子。注意:输入局面不一定是从初始局面合法走出来的。

输出格式

对于每个测试用例,输出一行:

  • 如果白方赢,输出white (xx)
  • 如果黑方赢,输出black (xx)

其中xx是步数(白方赢时步数为奇数,黑方赢时为偶数)。

题目分析与解题思路

本题是一个双方零和博弈问题,棋盘大小固定为4×44 \times 44×4,每方最多444个兵,状态空间有限,适合用极小化极大算法(Minimax\texttt{Minimax}Minimax配合记忆化搜索解决。

核心思路

  1. 状态表示
    棋盘共有161616格,每格有三种状态:空、白兵、黑兵。可以用222位二进制表示一格(000000空,010101白兵,101010黑兵),整个棋盘用一个646464位整数(unsigned long long)表示。另外还需要记录当前轮到谁走(000白方,111黑方)。

  2. 胜负判定

    • 白方赢:任意白兵到达第000行(黑方底线)。
    • 黑方赢:任意黑兵到达第333行(白方底线)。
    • 若当前玩家无合法走法(包括无兵可走),则对方赢。
  3. 走法生成
    根据当前玩家(白方或黑方)遍历所有兵:

    • 向前走:检查目标格是否在棋盘内且为空。
    • 吃子:检查左前、右前(对白方是行减111,对黑方是行加111)是否有对方兵。
  4. 搜索策略(Minimax\texttt{Minimax}Minimax
    solve(state,turn)solve(state, turn)solve(state,turn)返回(赢家,从当前状态到游戏结束的步数),其中turn=0turn = 0turn=0表示白方走,turn=1turn = 1turn=1表示黑方走。

    • 终止条件:出现胜负局面或无棋可走。
    • 递归过程
      • 生成所有合法走法。
      • 对每个走法递归调用solve(nextState,turn⊕1)solve(nextState, turn \oplus 1)solve(nextState,turn1)
      • 如果当前玩家能赢,则选择步数最少的走法(尽快赢)。
      • 如果当前玩家会输,则选择步数最多的走法(拖延)。
  5. 记忆化
    用哈希表缓存(state,turn)(state, turn)(state,turn)的结果,避免重复计算。

算法流程

  1. 读入棋盘,转换为646464位状态码。
  2. 调用solve(state,0)solve(state, 0)solve(state,0)(白方先走)。
  3. 根据返回的赢家和步数输出结果。

复杂度分析

  • 状态数:每格333种状态,最多316≈4.3×1073^{16} \approx 4.3 \times 10^73164.3×107,但实际可达状态远少于这个数(每方最多444个兵)。
  • 每个状态生成走法最多4×3=124 \times 3 = 124×3=12种(444个兵,每个兵最多333种走法:向前、左吃、右吃)。
  • 记忆化后,每个状态只计算一次,整体在时间和空间上均可接受。

代码实现

// The Pawn Chess// UVa ID: 10838// Verdict: Accepted// Submission Date: 2025-12-14// UVa Run Time: 0.000s//// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;// 棋盘编码:每格 2 位,共 16 格,64 位整数存储// 00: 空, 01: 白兵(P), 10: 黑兵(p)constintWHITE=1,BLACK=2;constintINF=1e9;// 方向:白兵向上(row-1),黑兵向下(row+1)constintWHITE_DIR=-1,BLACK_DIR=1;constintCAPTURE_DIRS[2][2]={{-1,-1},{-1,1}};// 白兵吃子方向(左上、右上)constintBLACK_CAPTURE_DIRS[2][2]={{1,-1},{1,1}};// 黑兵吃子方向(左下、右下)// 记忆化缓存:map<状态, pair<结果, 步数>>unordered_map<unsignedlonglong,pair<int,int>>memo[2];// 0:白方走, 1:黑方走// 从状态中获取某格的值intgetCell(unsignedlonglongstate,intr,intc){intpos=(r*4+c)*2;return(state>>pos)&3;}// 设置某格的值voidsetCell(unsignedlonglong&state,intr,intc,intval){intpos=(r*4+c)*2;state&=~(3ULL<<pos);state|=((unsignedlonglong)val<<pos);}// 判断是否到达底线boolisWhiteWin(unsignedlonglongstate){for(intc=0;c<4;++c)if(getCell(state,0,c)==WHITE)returntrue;// 白兵到达第0行(黑方底线)returnfalse;}boolisBlackWin(unsignedlonglongstate){for(intc=0;c<4;++c)if(getCell(state,3,c)==BLACK)returntrue;// 黑兵到达第3行(白方底线)returnfalse;}// 生成所有合法走法vector<pair<unsignedlonglong,int>>generateMoves(unsignedlonglongstate,intturn){vector<pair<unsignedlonglong,int>>moves;intplayer=(turn==0)?WHITE:BLACK;intdir=(turn==0)?WHITE_DIR:BLACK_DIR;for(intr=0;r<4;++r){for(intc=0;c<4;++c){if(getCell(state,r,c)!=player)continue;// 向前走一步intnr=r+dir;if(nr>=0&&nr<4&&getCell(state,nr,c)==0){unsignedlonglongnext=state;setCell(next,r,c,0);setCell(next,nr,c,player);moves.push_back({next,1});}// 吃子auto&capDirs=(turn==0)?CAPTURE_DIRS:BLACK_CAPTURE_DIRS;for(auto&d:capDirs){intnr=r+d[0];intnc=c+d[1];if(nr>=0&&nr<4&&nc>=0&&nc<4){inttarget=getCell(state,nr,nc);if(target!=0&&target!=player){unsignedlonglongnext=state;setCell(next,r,c,0);setCell(next,nr,nc,player);moves.push_back({next,1});}}}}}returnmoves;}// Minimax 搜索,返回 (胜负, 步数)pair<int,int>solve(unsignedlonglongstate,intturn){// 检查缓存if(memo[turn].count(state))returnmemo[turn][state];// 终局判断if(isWhiteWin(state))return{0,0};// 白方赢,步数为0(当前还未走)if(isBlackWin(state))return{1,0};// 黑方赢automoves=generateMoves(state,turn);if(moves.empty()){// 当前玩家无棋可走,对方赢if(turn==0)return{1,0};// 白方无棋,黑方赢elsereturn{0,0};// 黑方无棋,白方赢}intbestWinner=-1;intbestSteps=INF;intworstSteps=-1;for(auto&mv:moves){autores=solve(mv.first,turn^1);intwinner=res.first;intsteps=res.second+mv.second;// 加上这一步if(bestWinner==-1){bestWinner=winner;bestSteps=steps;worstSteps=steps;}else{if(winner==turn){// 当前玩家能赢,取最短步数if(winner==bestWinner)bestSteps=min(bestSteps,steps);else{bestWinner=winner;bestSteps=steps;}}else{// 当前玩家会输,取最长步数(拖延)if(bestWinner==winner)worstSteps=max(worstSteps,steps);else{// 如果之前有赢的可能,保留赢法if(bestWinner!=turn){bestWinner=winner;worstSteps=steps;}}}}}intfinalSteps=(bestWinner==turn)?bestSteps:worstSteps;memo[turn][state]={bestWinner,finalSteps};return{bestWinner,finalSteps};}intmain(){intT;cin>>T;while(T--){vector<string>board(4);for(inti=0;i<4;++i){cin>>board[i];// 处理可能的空格(样例中有空格,但实际输入可能没有)if(board[i].size()<4)board[i]="....";}// 构建状态unsignedlonglongstate=0;for(intr=0;r<4;++r){for(intc=0;c<4;++c){intval=0;if(board[r][c]=='P')val=WHITE;elseif(board[r][c]=='p')val=BLACK;setCell(state,r,c,val);}}// 初始化缓存memo[0].clear();memo[1].clear();autores=solve(state,0);intwinner=res.first;intsteps=res.second;if(winner==0)cout<<"white ("<<steps<<")\n";elsecout<<"black ("<<steps<<")\n";}return0;}

总结

本题是一道典型的博弈搜索题,通过状态压缩和记忆化搜索可以在有限时间内求解。关键在于理解Minimax\texttt{Minimax}Minimax搜索中“赢方尽快、输方拖延”的策略,并正确实现走法生成与胜负判断。代码中使用了646464位整数表示棋盘状态,提高了存储和计算效率,适合题目给定的数据范围。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/30 1:11:17

EVF8602-E-V009逆变器

EVF8602-E-V009 是 LENZE&#xff08;伦茨&#xff09;生产的一款高性能交流变频器&#xff08;逆变器&#xff09;&#xff0c;主要用于工业自动化系统中对三相异步电机或伺服电机进行速度、转矩和位置控制。以下是详细信息整理&#xff1a;EVF8602-E-V009 逆变器主要特点宽调…

作者头像 李华
网站建设 2026/1/27 15:51:01

惠普M1005打印机驱动下载与安装指南:告别故障,高效办公不卡顿!

“惠普M1005驱动安装失败&#xff0c;80%不是设备问题而是渠道错了&#xff01;”“惠普M1005打印机驱动找不到”&#xff0c;“安装后无法打印”“驱动与系统不兼容”&#xff1f;。惠普M1005作为经典的多功能打印机&#xff0c;凭借稳定性能成为职场办公、小型打印店、家庭使…

作者头像 李华
网站建设 2026/1/29 3:12:07

戴西HPC高性能计算平台:为工业仿真打造的专业计算引擎

在工业产品研发进入数字化深水区的今天&#xff0c;仿真计算正在从“辅助设计”转变为“研发核心驱动力”。更复杂的模型、更精细的网格、更长的求解时间&#xff0c;使得企业急需一个稳定、灵活、可视化且易用的高性能计算平台&#xff0c;帮助工程师从传统单机的性能瓶颈和算…

作者头像 李华
网站建设 2026/1/28 3:36:49

上门家政小程序运营模式:3 个月用户破 5 万,复购率 75% 的赚钱逻辑

一、核心运营逻辑&#xff1a;破解 3 大行业痛点&#xff0c;立足本地化刚需​上门家政的运营核心&#xff0c;是抓住 “同城刚需 信任稀缺 服务标准化” 三大关键点&#xff0c;破解行业 “获客难、纠纷多、复购低” 痛点&#xff0c;头部平台实现 3 个月同城用户破 5 万、复…

作者头像 李华
网站建设 2026/1/29 19:14:56

18、深入解析域名服务(DNS):原理、架构与应用

深入解析域名服务(DNS):原理、架构与应用 1. 域名系统(DNS)概述 域名系统(DNS)克服了主机表的两大主要弱点: - 可扩展性强 :它并非依赖单一的大表,而是分布式数据库系统,不会随着数据库的增长而变慢。目前,DNS能提供约1600万台主机的信息,而主机表中列出的主…

作者头像 李华
网站建设 2026/1/26 2:28:38

【李沐 | 动手实现深度学习】9-1 Pytorch神经网络基础

每天起床第一句&#xff0c;“你今天Deep Learning”了吗&#x1f60d;&#x1f60d;hahaha &#x1f62d;&#x1f62d;每天一睁眼就困&#x1f62a;&#x1f62a;。。。 今天的内容比较简单&#xff0c;第5章深度网络计算 ~~~ 我觉得可以不用敲代码&#xff0c;理解就可以啦…

作者头像 李华