P10386 [蓝桥杯 2024 省 A] 五子棋对弈题解复盘

📅 2026/7/26 1:19:25 👁️ 阅读次数 📝 编程学习
P10386 [蓝桥杯 2024 省 A] 五子棋对弈题解复盘

五子棋平局(蓝桥杯填空题)题解复盘

基本信息

项目内容
题目编号、来源蓝桥杯 五子棋平局(结果填空题)
训练层级B DFS + 回溯
知识版块DFS、回溯、棋盘枚举、状态压缩

解题前・关键信号识别

维度分析
目标、约束、底层结构目标:5×5 棋盘,白棋先手共 13 个,黑棋 12 个,终局无人五子连珠,求平局终局数量;约束:棋盘 25 格,每格三种状态(空/白/黑),但终局无空格;底层结构:DFS 枚举 25 个格子的黑白状态,回溯恢复棋盘,剪枝限制棋子数量。
数据规模25 个格子,每个格子 2 种状态(白/黑),总终局数 C(25,13) = 5,200,300,DFS 枚举所有方案完全可行。
候选算法和依据DFS + 回溯;依据:每个格子只有白/黑两种终局状态,按顺序逐格枚举,用剪枝减少搜索量。
复杂度预判时间复杂度 O(2^25),但剪枝后大幅减少;空间复杂度 O(25)。

解题后・外化复盘

维度内容
实现结构 / 核心思路第一步从 (0,0) 开始 DFS,逐格处理每个格子放白棋或黑棋;第二步每步检查白棋是否超过 13 个、黑棋是否超过 12 个,超过则剪枝返回;第三步当 25 个格子全部处理完(x==5),检查白棋是否恰好 13 个、黑棋恰好 12 个,且无人五子连珠,满足则 ans++;第四步定义 check() 函数检查 5 行、5 列、2 条对角线是否有五个相同棋子;第五步输出 ans。核心思想:枚举所有终局状态,筛选满足棋子数量且无人获胜的平局局面。
错因回溯1. 剪枝条件放在出口后面,导致白棋超过 13 个的非法状态也被计入 ans;2. 出口处没有检查white == 13 && black == 12,导致棋子数量不对的终局也被计入;3. check() 函数用return true表示有人赢,调用时用!check()表示平局,逻辑正确但容易混淆;4. 忘记回溯恢复board[x][y] = 0,导致棋盘状态被污染。
边界和易错点1. 剪枝条件 `if (white > 13
下次看到什么信号,我应该想到这个方法看到「棋盘 + 黑白棋子 + 平局 + 结果填空」,用 DFS 枚举所有终局状态 + 回溯。

AC 完整代码

#include<iostream>usingnamespacestd;intboard[5][5];intans=0;boolcheck(){for(inti=0;i<5;i++){if(board[i][0]!=0&&board[i][0]==board[i][1]&&board[i][1]==board[i][2]&&board[i][2]==board[i][3]&&board[i][3]==board[i][4]){returntrue;}if(board[0][i]!=0&&board[0][i]==board[1][i]&&board[1][i]==board[2][i]&&board[2][i]==board[3][i]&&board[3][i]==board[4][i]){returntrue;}}if(board[0][0]!=0&&board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[2][2]==board[3][3]&&board[3][3]==board[4][4]){returntrue;}if(board[0][4]!=0&&board[0][4]==board[1][3]&&board[1][3]==board[2][2]&&board[2][2]==board[3][1]&&board[3][1]==board[4][0]){returntrue;}returnfalse;}voiddfs(intx,inty,intwhite,intblack){if(white>13||black>12)return;if(x==5){if(white==13&&black==12&&!check())ans++;return;}intnx=x,ny=y+1;if(ny==5){nx=x+1;ny=0;}board[x][y]=1;dfs(nx,ny,white+1,black);board[x][y]=2;dfs(nx,ny,white,black+1);board[x][y]=0;}intmain(){dfs(0,0,0,0);cout<<ans<<endl;return0;}