1004 四子连棋
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题目描述 Description
在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,
任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑
白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。
● ○ ●
○ ● ○ ●
● ○ ● ○
○ ● ○
输入描述 Input Description
从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。
输出描述 Output Description
用最少的步数移动到目标棋局的步数。
样例输入 Sample Input
BWBO
WBWB
BWBW
WBWO
样例输出 Sample Output
5
数据范围及提示 Data Size & Hint
hi
**************代码有点冗长了。。但是思路最重要,不要看别人的题解,费神费力。
************自己理解了按自己想法先做着吧(确定自己思路后管它对不对做了再说)
#include<iostream>
#include<string.h>
#include<cstdlib>
#include<cstdio>
using namespace std;
typedef struct
{
int map[16]; // B -> 1 , W -> 2
int pre; //上一次走的棋
}QUEUE;
QUEUE q[1000000];
int head = 0,tail = 1,step = 1;
int dx[4] = {-1,1,0,0} , dy[4] = {0,0,-1,1};
bool v[1000];
int check_status(int *nstatus) //判重:棋子代号*位置(也不知是不是真的靠谱,但是过了)
{
int cnt = 0;
for(int i = 0; i < 16; i++)
cnt += nstatus[i]*(i+1);
return cnt;
}
bool check_reachgoal(int *a) //有错,见评论,谢谢!
{
if( (a[0] == a[1] && a[1] == a[2] && a[2] == a[3]) ||
(a[4] == a[5] && a[5] == a[6] && a[6] == a[7]) ||
(a[8] == a[9] && a[9] == a[10] && a[10] == a[11]) ||
(a[12] == a[13] && a[13] == a[14] && a[14] == a[15]) ) { cout<<"1 a!"<<endl; return true;} //横行
if( (a[0] == a[4] && a[4] == a[8] && a[8] == a[12]) ||
(a[1] == a[5] && a[5] == a[9] && a[9] == a[13]) ||
(a[2] == a[6] && a[6] == a[10] && a[10] == a[14]) ||
(a[3] == a[7] && a[7] == a[11] && a[11] == a[15]) ) { cout<<"2 a!"<<endl; return true; } //竖行
if( (a[0] == a[5] && a[5] == a[10] && a[10] == a[15]) ||
(a[3] == a[6] && a[6] == a[9] && a[9] == a[12]) ) { cout<<"2 a!"<<endl; return true; } //斜行
return false; //注意return false否则会return true;
}
void bfs()
{
int qi,i,j,r = 0,oldtail;
int ox[2],oy[2],ol[2],nx,ny,nl;
QUEUE nstatus;
//第一次走棋特殊考虑
for(i = 0; i < 16; i++) //找空格
if(!q[0].map[i])
{
ox[r] = i/4 , oy[r] = i%4 , ol[r] = i;
r++;
}
for(i = 0; i < 2; i++) //第0,1个空格分别产生情况
{
for(j = 0; j < 4; j++)
{
nx = ox[i] + dx[j] , ny = oy[i] + dy[j];
nl = nx*4+ny;
if(nx >= 0 && ny >= 0 && nx < 4 && ny < 4 && q[0].map[nl])
{
memcpy(nstatus.map,q[0].map,sizeof(nstatus.map)); //产生新状态
nstatus.pre = nstatus.map[nl];
nstatus.map[nl] = 0;
nstatus.map[ol[i]] = q[0].map[nl];
/* test : check_reachgoal少了最后的return true;
for(int ti = 0; ti < 16; ti++)
cout<<nstatus.map[ti];
cout<<endl;
*/
if(check_reachgoal(nstatus.map))
{
// cout<<"no"<<endl;
cout<<step<<endl;
exit(0);
}
q[tail++] = nstatus;
v[check_status(nstatus.map)] = 1;
}
}
}
head++ , step++;
while(head < tail)
{
oldtail = tail;
for(qi = head; qi < oldtail; qi++)
{
r = 0;
for(i = 0; i < 16; i++) //找空格
{
if(!q[qi].map[i])
{
ox[r] = i/4 , oy[r] = i%4 , ol[r] = i;
r++;
}
}
for(i = 0; i < 2; i++) //第0,1个空格分别产生情况
{
for(j = 0; j < 4; j++)
{
nx = ox[i] + dx[j] , ny = oy[i] + dy[j];
nl = nx*4+ny;
if(nx >= 0 && ny >= 0 && nx < 4 && ny < 4 && q[qi].map[nl] != q[qi].pre && q[qi].map[nl])
{
memcpy(nstatus.map,q[qi].map,sizeof(nstatus.map));
nstatus.pre = nstatus.map[nl];
nstatus.map[nl] = 0;
nstatus.map[ol[i]] = q[qi].map[nl];
if(check_reachgoal(nstatus.map))
{
cout<<step<<endl;
exit(0);
}
if(!v[check_status(nstatus.map)]) q[tail++] = nstatus;
}
}
}
}
head = oldtail;
step++;
}
}
int main()
{
memset(v,0,sizeof(v));
char a;
int i,r = 0;
for(i = 0; i < 16; i++)
{
cin>>a;
if(a == 'B') q[0].map[i] = 1;
else if(a == 'W') q[0].map[i] = 2;
else q[0].map[i] = 0;
}
bfs();
return 0;
}
*************************************************************************仅供吐槽
1004 四子连棋(思路重要)
最新推荐文章于 2020-08-07 20:25:03 发布