版权声明:沃斯里德小浩浩啊 https://blog.csdn.net/Healer66/article/details/82491437
题目链接:https://odzkskevi.qnssl.com/6fd8c99567698f4bad5a228cc982bad7?v=1535352582
题意:
给出先手黑棋的位置(1,x)和最后一子白棋的位置(x1,y1),三子相连即胜利,问最后白棋获胜的可能状态有多少种,每次只能下在某一列的最低位置处。
思路:
dfs模拟下棋,详见代码:
#include<bits/stdc++.h>
#include<unordered_set>
using namespace std;
const int N=4+2;
int a[N][N],cnt[N];//cnt用来记录每列已经下了多少棋子
int X0,X1,Y1,ans;
unordered_set<unsigned int> vis;
unsigned int state()
{
unsigned int sum=0;
for(int i=0; i<=3; ++i)
for(int j=0; j<=3; ++j)
sum=sum<<2|a[j][i];//确保状态唯一性
return sum;
}
bool win(int p)
{
for(int x=0; x<=3; ++x)
for(int y=0; y<=3; ++y)
{
if(x+2<=3&&a[x][y]==p&&a[x+1][y]==p&&a[x+2][y]==p)return true;//竖
if(y+2<=3&&a[x][y]==p&&a[x][y+1]==p&&a[x][y+2]==p)return true;//横
if(x+2<=3&&y+2<=3&&a[x][y]==p&&a[x+1][y+1]==p&&a[x+2][y+2]==p)return true;//右上
if(x-2>=0&&y+2<=3&&a[x][y]==p&&a[x-1][y+1]==p&&a[x-2][y+2]==p)return true;//左上
}
return false;
}
void dfs(int p)
{
unsigned int k=state();
if(vis.count(k))return;
vis.insert(k);
if(win(1)||win(2)||a[X1][Y1])
{
if(win(2)&&a[X1][Y1]==2)
++ans;//以白棋在x1,y1处结尾且白棋连续
return;
}
for(int x=0; x<=3; ++x)//四列分别放棋
{
if(cnt[x]==4)continue;
a[x][cnt[x]++]=p;
dfs(p^3);//p=2时p^3为1,反之为2(按位异或,不同为1,相同为0)
a[x][--cnt[x]]=0;//回溯
}
}
int main()
{
scanf("%d%d%d",&X0,&Y1,&X1);
X0--,Y1--,X1--;//下标从0开始
a[X0][cnt[X0]++]=1;//1代表黑,2代表白
dfs(2);
printf("%d\n",ans);
return 0;
}