版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a54665sdgf/article/details/82153986
题意:两个人轮流从棋盘上分别放置黑白两色的棋子,每次只能从最低位放置。给你规定第一枚黑棋和最后一枚白棋放置的位置,让你求出总共有多少种局面,使得该局面白棋胜利。(横竖斜至少有一个方向存在连续的三枚同色棋子即可胜利)
思路:一看到从低位到高位,首先想到dp,再一想,要判断是否胜利需要用到下面棋子的状态,不可取,放弃。
然后就是dfs了,没什么技巧,就是纯粹的模拟放置棋子的过程。注意当某一列棋子放满之后就不能继续放了,而且若当前局面已有一方胜利或者有棋子放置在终点的时候要return。若放置在终点的棋子为白棋并且白棋此时能赢,则++ans。
另外要用set来保存当前局面的状态,以防重复。
比赛的时候脑子崩了,狂出bug...
#define FRER() freopen("i.txt","r",stdin)
#define FREW() freopen("o.txt","w",stdout)
#define dbg puts("--------------------");
#include<bits/stdc++.h>
#include<unordered_set>
typedef long long ll;
using namespace std;
const int N=4+2;
int a[N][N];
int cnt[N];
int X0,X1,Y1;
int ans;
ll state()
{
ll key=0;
for(int i=3; i>=0; --i)
for(int j=0; j<=3; ++j)
key=key*3+a[j][i];
return key;
}
unordered_set<ll> vis;
bool win(int p)
{
for(int y=0; y<=3; ++y)
for(int x=0; x<=1; ++x)
if(a[x][y]==p&&a[x+1][y]==p&&a[x+2][y]==p)return true;
for(int x=0; x<=3; ++x)
for(int y=0; y<=1; ++y)
if(a[x][y]==p&&a[x][y+1]==p&&a[x][y+2]==p)return true;
if(a[0][2]==p&&a[1][1]==p&&a[2][0]==p)return true;
if(a[0][3]==p&&a[1][2]==p&&a[2][1]==p)return true;
if(a[1][2]==p&&a[2][1]==p&&a[3][0]==p)return true;
if(a[1][3]==p&&a[2][2]==p&&a[3][1]==p)return true;
if(a[0][1]==p&&a[1][2]==p&&a[2][3]==p)return true;
if(a[0][0]==p&&a[1][1]==p&&a[2][2]==p)return true;
if(a[1][1]==p&&a[2][2]==p&&a[3][3]==p)return true;
if(a[1][0]==p&&a[2][1]==p&&a[3][2]==p)return true;
return false;
}
void dfs(int p)
{
ll 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;
return;
}
for(int x=0; x<4; ++x)
{
if(cnt[x]==4)continue;
int y=cnt[x];
a[x][cnt[x]++]=p;
dfs(p^3);
a[x][y]=0;
cnt[x]--;
}
}
int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);
scanf("%d%d%d",&X0,&Y1,&X1);
X0--,Y1--,X1--;
a[X0][cnt[X0]++]=1;
dfs(2);
printf("%d\n",ans);
return 0;
}
//