问题描述
“在五子棋的对弈中,友谊的小船说翻就翻?”
不!对小蓝和小桥来说,五子棋不仅是棋盘上的较量,更是心与心之间的沟通。
这两位挚友秉承着“友谊第一,比赛第二” 的宗旨,决定在一块5 × 5 的棋盘上,用黑白两色的棋子来决出胜负。
但他们又都不忍心让对方失落,于是决定用一场和棋(平局)作为彼此友谊的见证。
比赛遵循以下规则:
- 棋盘规模:比赛在一个5 × 5 的方格棋盘上进行,共有25 个格子供下棋使用。
- 棋子类型:两种棋子,黑棋与白棋,代表双方。小蓝持白棋,小桥持黑棋。
- 先手规则:白棋(小蓝)具有先手优势,即在棋盘空白时率先落子(下棋)。
- 轮流落子:玩家们交替在棋盘上放置各自的棋子,每次仅放置一枚。
- 胜利条件:率先在横线、竖线或斜线上形成连续的五个同色棋子的一方获胜。
- 平局条件:当所有25 个棋盘格都被下满棋子,而未决出胜负时,游戏以平局告终。
在这一设定下,小蓝和小桥想知道,有多少种不同的棋局情况,既确保棋盘下满又保证比赛结果为平局。
终局不同看成不同情况,终局相同而落子顺序不同看成同一种情况。
本题的结果为一个整数,在提交答案时只输出这个整数,输出多余的内容将无法得分。
格式输入
无
格式输出
一个整数
评测用例规模与约定
无
解析
dfs爆搜,所有情况搜出来进行判断是不是平局,同时注意判断条件。主要是check和dfs这逻辑写好就能做出来。有大佬用状压dp做。。。
参考程序
#include<bits/stdc++.h>
using namespace std;
const int N=5;
int dp[N][N];//存储棋盘状态1白2黑
int ans;//计方案数
bool check()//检查是否为平局
{
for(int i=0;i<N;i++)//检查行
{
if(dp[i][0]==-1)continue;
bool ok=true;
for(int j=1;j<N;j++)
if(dp[i][j]!=dp[i][0])
{
ok=false;
break;
}
if(ok)return true;
}
for(int j=0;j<N;j++)//检查列
{
if(dp[0][j]==-1)continue;
bool ok=true;
for(int i=1;i<N;i++)
if(dp[i][j]!=dp[0][j])
{
ok=false;
break;
}
if(ok)return true;
}
if(dp[0][0]!=-1)//检查主对角线
{
bool ok=true;
for(int i=1;i<N;i++)
if(dp[i][i]!=dp[0][0])
{
ok=false;
break;
}
if(ok)return true;
}
if(dp[0][N-1]!=-1)//检查副对角线
{
bool ok=true;
for(int i=1;i<N;i++)
if(dp[i][N-1-i]!=dp[0][N-1])
{
ok=false;
break;
}
if(ok)return true;
}
return false;
}
void dfs(int x,int y)//dfs
{
if(check())return;//检查成功是平局return
if(x==N)
{
int sum=0;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
if(dp[i][j]==1)sum+=dp[i][j];
if(sum==13)ans++;//一共25个格子,白的13够了
return;
}
int dx=x,dy=y;
if(y+1<N)dy++;else dy=0,dx++;
dp[x][y]=1;//放白棋
dfs(dx,dy);
dp[x][y]=2;//放黑棋
dfs(dx,dy);
dp[x][y]=-1;//回溯
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
memset(dp,-1,sizeof(dp));//初始化设为-1;
dfs(0,0);
cout<<ans;
return 0;
}
难度等级
⭐️⭐️⭐️再加半颗(1~10星)
以个人刷题整理为目的,如若侵权,请联系删除~