题意分析
BFS很好想,要考虑白色先手和黑色先手两种情况。
移动棋子可以理解为移动空白部分,搜索时要注意:
1. 空白部分不能出界
2. 空白部分不能重叠
3. 移动的棋子要和当前对应要移动的棋子相同
判重的话,直接用hash就可以。
这个题hash冲突概率很低了,随便蛤蛤就可以了。
代码总览
#include<bits/stdc++.h>
using namespace std;
const int nmax = 100000;
const int INF = 0x3f3f3f3f;
const int MOD = 3733799;
const int ntx[] = {0,0,1,-1};
const int nty[] = {1,-1,0,0};
typedef struct{
int board[4][4];
int x[2],y[2];
int step;
int turn;
}status;
status now,news;
char bb[4][4];
bitset<4000000> visit;
void debug(const status & s){
for(int i = 0;i<4;++i){
for(int j = 0;j<4;++j){
printf("%d ",s.board[i][j]);
}
if(i != 3) printf("\n");
else printf(" %d %d\n",s.step,s.turn);
}
printf("\n");
}
inline bool judge(const int & x ,const int & y){
if(x < 0 || x>=4 || y < 0 || y>=4) return false;
return true;
}
inline int gethash(const status & s){
int hh = 0,k = 1;
for(int i = 0;i<4;++i)
for(int j = 0;j<4;++j){
hh = hh *3 + s.board[i][j] ;
}
hh %= MOD;
return hh;
}
inline bool check(const status & s){
int temp[3] = {0};
for(int i = 0;i<4;++i){
temp[0] = temp[1] = temp[2] = 0;
for(int j = 0;j<4;++j) temp[s.board[i][j]]++;
if(temp[1] == 4 || temp[2] == 4) return true;
temp[0] = temp[1] = temp[2] = 0;
for(int j = 0;j<4;++j) temp[s.board[j][i]]++;
if(temp[1] == 4 || temp[2] == 4) return true;
}
temp[0] = temp[1] = temp[2] = 0;
for(int i = 0;i<4;++i) temp[s.board[i][i]] ++;
if(temp[1] == 4 || temp[2] ==4) return true;
temp[0] = temp[1] = temp[2] = 0;
for(int i = 0;i<4;++i) temp[s.board[i][3-i]] ++;
if(temp[1] == 4 || temp[2] ==4) return true;
return false;
}
int bfs(){
queue<status> q; q.push(now); visit.set(gethash(now));
now.turn = 2; q.push(now);
while(!q.empty()){
now = q.front(); q.pop();
if(check(now)) { return now.step;}
for(int i = 0;i<2;++i){
for(int j = 0;j<4;++j){
news = now;
int ox = news.x[i], oy = news.y[i];
int nx = ox + ntx[j] , ny = oy + nty[j];
if(judge(nx,ny) && news.board[nx][ny] != 0 ){
if(news.turn != news.board[nx][ny] ) { continue;}
swap(news.board[ox][oy],news.board[nx][ny]);
if(visit[gethash(news)] == 0){
visit.set(gethash(news));
news.x[i] = nx; news.y[i] = ny;
news.step = now.step + 1;
news.turn = (now.turn== 1?2:1);
q.push(news);
// debug(news);
}
}
}
}
}
return -1;
}
int main(){
visit.reset();
bool isfirst = true;
for(int i = 0;i<4;++i) scanf("%s",bb[i]);
for(int i = 0;i<4;++i){
for(int j = 0;j<4;++j){
if(bb[i][j] == 'B') now.board[i][j] = 2;
if(bb[i][j] == 'W') now.board[i][j] = 1;
if(bb[i][j] == 'O') {
now.board[i][j] = 0;
if(isfirst) now.x[0] = i, now.y[0] = j, isfirst = false;
else now.x[1] = i, now.y[1] = j;
}
}
}
now.step = 0;
now.turn = 1;
printf("%d\n",bfs());
return 0;
}