题目链接
题目大意:给你4个棋子的坐标,给你最终状态的4个坐标,每个棋子可以走4个方向,入过下一步是空格则可以走,想一步是棋子则走到对应的下一个位置(要是空格才可以,是棋子就不可以),问在8步之内能否走到;
思路:开8维char数组记录4个棋子的坐标,int会MLE;同时从两个方向搜索,如果在8步内某个状态搜到了相反状态则找到答案,否则没有答案;sort是用来简化状态的比如1 1 2 2 3 3 4 4和3 3 4 4 2 2 1 1是一样的,不sort状态会很多;我定义的初始状态向末态的状态是1相反为2;
我看有的人单想广搜也能过,就是要加上剪枝,当前状态到最终状态的最少步数,比剩余步数多则减掉;
可以将两个点放在同一个队列里,我是用了两个队列,先将初始状态走4步,得到标记后,用第二个搜第一个状态;一个队列应该不会炸;
#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
char flag[8][8][8][8][8][8][8][8];
int z[4][2]= {-1,0,1,0,0,-1,0,1};
struct zp
{
int x,y;//坐标
};
struct zp1
{
zp cp[4];//4个棋子的坐标
int step;//步数
char num;//哪种状态
} s,e;
int cmp(zp a,zp b)//用来给4个棋子排序减少状态
{
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
int check(zp1 a,int i,int j)//判断下一步是什么
{
int x=a.cp[i].x+z[j][0],y=a.cp[i].y+z[j][1];
if(x>=0&&x<8&&y>=0&&y<8)
{
for(int k=0; k<4; k++)
{
if(k!=i&&a.cp[k].x==x&&a.cp[k].y==y)
return 1;//是棋子
}
return 2;//是空格
}
return 0;//越界
}
void make_set(zp1 a)//标记
{
flag[a.cp[0].x][a.cp[0].y][a.cp[1].x][a.cp[1].y][a.cp[2].x][a.cp[2].y][a.cp[3].x][a.cp[3].y]=a.num;
}
int get_ans(zp1 a)//是否得到答案
{
char ss=flag[a.cp[0].x][a.cp[0].y][a.cp[1].x][a.cp[1].y][a.cp[2].x][a.cp[2].y][a.cp[3].x][a.cp[3].y];
if(ss==a.num)//相同状态的访问
return -1;
else if(ss=='0')//没有访问过
return -2;
else return 1;//不同状态的访问
}
int dbfs()
{
memset(flag,'0',sizeof(flag));
queue<zp1> q[2];
s.step=0,s.num='1';
e.step=0,s.num='2';
make_set(s);
if(get_ans(e)==1)//起始状态与终止状态相同
return 1;
make_set(e);
q[0].push(s);
q[1].push(e);
int in=0;
while((!q[0].empty())||(!q[1].empty()))//伪双广搜
{
if(q[0].empty()) in=1;
zp1 u=q[in].front();
q[in].pop();
if(u.step>=4)
continue;
for(int i=0; i<4; i++)//4个棋子
{
for(int j=0; j<4; j++)//4个方向
{
zp1 v=u;
int ss=check(v,i,j);//判断v状态第i个棋子走j方向的状态
if(ss==1)//棋
{
v.cp[i].x+=z[j][0];
v.cp[i].y+=z[j][1];
ss=check(v,i,j);
if(ss==2)//空
{
v.cp[i].x+=z[j][0];
v.cp[i].y+=z[j][1];
sort(v.cp,v.cp+4,cmp);
v.step++;
ss=get_ans(v);//判断v状态是否出现过
if(ss==-1)//相同状态出现
continue;
else if(ss==1)//不同状态出现
return 1;
make_set(v);//标记
q[in].push(v);
}
}
else if(ss==2)//空
{
v.cp[i].x+=z[j][0];
v.cp[i].y+=z[j][1];
sort(v.cp,v.cp+4,cmp);
v.step++;
ss=get_ans(v);
if(ss==-1)
continue;
else if(ss==1)
return 1;
make_set(v);
q[in].push(v);
}
}
}
}
return 0;
}
int main()
{
while(~scanf("%d%d",&s.cp[0].x,&s.cp[0].y))//注意下标要减1讲1-8变成0-7
{
s.cp[0].x--;
s.cp[0].y--;
for(int i=1; i<4; i++)
{
scanf("%d%d",&s.cp[i].x,&s.cp[i].y);
s.cp[i].x--;
s.cp[i].y--;
}
for(int i=0; i<4; i++)
{
scanf("%d%d",&e.cp[i].x,&e.cp[i].y);
e.cp[i].x--;
e.cp[i].y--;
}
sort(s.cp,s.cp+4,cmp);
sort(e.cp,e.cp+4,cmp);
if(dbfs())
printf("YES\n");
else
printf("NO\n");
}
}