news 2026/7/7 21:37:12

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/7/7 7:56:27

SGMG-05V2AB伺服编码器

SGMG‑05V2AB 是安川&#xff08;Yaskawa&#xff09; SGMG 系列伺服电机型号&#xff0c;它内置的伺服编码器用于实现高精度位置和速度反馈。虽然型号是整机电机&#xff0c;但其编码器是控制精度的关键部件。SGMG‑05V2AB 内置编码器特点高分辨率反馈多为增量式编码器&#x…

作者头像 李华
网站建设 2026/7/7 9:32:52

SRM50-HWA0-K22 伺服电机

SRM50-HWA0-K22 是 SICK 公司出品的伺服电机型号&#xff0c;主要用于精密定位和运动控制系统中&#xff0c;适配高性能伺服驱动器&#xff0c;实现闭环控制。以下是整理的详细信息&#xff1a;SRM50-HWA0-K22 伺服电机主要特点高精度闭环控制提供位置、速度和力矩反馈重复定位…

作者头像 李华
网站建设 2026/7/7 19:29:31

微服务架构设计 - 高并发缓存设计

决胜毫秒级:车贷核心系统的高并发缓存架构实战与方法论 在车贷金融领域,用户体验与风控效率是天平的两端。进件系统的响应速度直接决定了转化率,而额度查询的准确性则关乎资金安全。面对日均百万级的调用和瞬间的流量洪峰,简单的“Redis get/set”已无法满足生产环境的严苛…

作者头像 李华
网站建设 2026/7/6 19:46:19

LobeChat能否实现数据库持久化存储?避免数据丢失的关键

LobeChat 能否实现数据库持久化存储&#xff1f;避免数据丢失的关键 在如今大模型应用爆发的背景下&#xff0c;越来越多开发者选择搭建私有化的 AI 对话系统。LobeChat 凭借其简洁现代的界面、对主流大模型的良好支持以及高度可扩展的插件体系&#xff0c;迅速成为个人用户和小…

作者头像 李华
网站建设 2026/7/7 2:49:33

Qwen3-8B镜像安装全攻略:轻松部署高性价比大模型

Qwen3-8B镜像安装全攻略&#xff1a;轻松部署高性价比大模型 在AI应用快速落地的今天&#xff0c;越来越多开发者面临一个现实问题&#xff1a;如何在有限预算和硬件条件下&#xff0c;运行一个真正“能用、好用”的大语言模型&#xff1f;许多开源模型虽然参数庞大、宣传亮眼&…

作者头像 李华
网站建设 2026/7/7 0:34:54

XC7Z020-2CLG484I, 双核ARM Cortex-A9处理器, 现货库存

型号介绍今天我要向大家介绍的是 Xilinx 的一款处理器——XC7Z020-2CLG484I。 它搭载了相当规模的FPGA逻辑资源&#xff0c;包括278,624个逻辑单元、36个18x18位的DSP48E1乘法器、2个块RAM&#xff08;Block RAM&#xff09;以及大量的分布式RAM和移位寄存器。PL部分允许用户实…

作者头像 李华