题解 P3930 【SAC E#1 - 一道大水题 Knight】
这里是一个学DFS学傻了,忘了如何写BFS的蒟蒻的记搜题解。
看到最小步数,考虑IDDFS。
棋子的攻击范围可以直接覆盖并叠加,在吃掉棋子后暴力消除覆盖即可。
直接记录剩余i步时在
代码很长,请酌情阅读。
#include<cstdio>
#include<cstring>
#define reg register
#define MAXN 60
using namespace std;
const int dx[8]={1,1,2,2,-1,-1,-2,-2};
const int dy[8]={2,-2,1,-1,2,-2,1,-1};
int ban[MAXN][MAXN],dp[MAXN][MAXN][505];//dp记搜,ban记录覆盖情况
char map[MAXN][MAXN];
int n,x,y,ex,ey;
inline bool inmap(char ch)
{return(ch=='.'||ch=='O'||ch=='C'||ch=='K'||ch=='B'||ch=='Q'||ch=='X'||ch=='P');}
inline bool out(int x,int y)//越界
{return(x<1||x>n||y<1||y>n);}
inline int trans(char ch)
{
if(ch=='C')
return(1);
if(ch=='K')
return(4);
if(ch=='X')
return(5);
if(ch=='B')
return(2);
if(ch=='Q')
return(3);
if(ch=='P')
return(6);
return(7);
}
inline void cover(int type,int px,int py,int val)
{
if(type>6)
return;
if(type==6)//兵
{
if(!out(px+1,py-1))
ban[px+1][py-1]+=val;
if(!out(px+1,py+1))
ban[px+1][py+1]+=val;
return;
}
if(type==5)//王
{
if(!out(px+1,py-1))
ban[px+1][py-1]+=val;
if(!out(px+1,py+1))
ban[px+1][py+1]+=val;
if(!out(px+1,py))
ban[px+1][py]+=val;
if(!out(px-1,py+1))
ban[px-1][py+1]+=val;
if(!out(px-1,py-1))
ban[px-1][py-1]+=val;
if(!out(px-1,py+1))
ban[px-1][py]+=val;
if(!out(px,py-1))
ban[px][py-1]+=val;
if(!out(px,py+1))
ban[px][py+1]+=val;
return;
}
if(type==4)//马
{
if(!out(px-1,py-2))
ban[px-1][py-2]+=val;
if(!out(px-1,py+2))
ban[px-1][py+2]+=val;
if(!out(px+1,py-2))
ban[px+1][py-2]+=val;
if(!out(px+1,py+2))
ban[px+1][py+2]+=val;
if(!out(px-2,py-1))
ban[px-2][py-1]+=val;
if(!out(px-2,py+1))
ban[px-2][py+1]+=val;
if(!out(px+2,py-1))
ban[px+2][py-1]+=val;
if(!out(px+2,py+1))
ban[px+2][py+1]+=val;
}
for(reg int i=1;i<=n;i++)//车、象和后,暴力覆盖
{
if(type&1)
{
if(!out(px-i,py))
ban[px-i][py]+=val;
if(!out(px+i,py))
ban[px+i][py]+=val;
if(!out(px,py-i))
ban[px][py-i]+=val;
if(!out(px,py+i))
ban[px][py+i]+=val;
}
if(type&2)
{
if(!out(px-i,py-i))
ban[px-i][py-i]+=val;
if(!out(px+i,py+i))
ban[px+i][py+i]+=val;
if(!out(px+i,py-i))
ban[px+i][py-i]+=val;
if(!out(px-i,py+i))
ban[px-i][py+i]+=val;
}
}
return;
}
bool dfs(int rest,int px,int py)
{
if(rest==0)
return(px==ex&&py==ey);
if(dp[px][py][rest])
return(dp[px][py][rest]==2);
bool res=false;
for(reg int i=0;i<8;i++)
{
int qx=px+dx[i],qy=py+dy[i];
if(out(qx,qy)||(ban[qx][qy]&&(qx!=ex||qy!=ey)))
continue;
char tmp=map[qx][qy];
if(tmp!='.')
map[qx][qy]='.';
cover(trans(tmp),qx,qy,-1);
res|=dfs(rest-1,qx,qy);
cover(trans(tmp),qx,qy,1);
map[qx][qy]=tmp;
if(res)
return(dp[px][py][rest]=2,true);
}
return(dp[px][py][rest]=res?2:1,res);
}
int main()
{
while(scanf("%d",&n)!=EOF)//多组数据
{
memset(ban,0,sizeof(ban));
memset(dp,0,sizeof(dp));
for(reg int i=1,j=0;i<=n;i++)
{
char ch=getchar();
while(!inmap(ch))
ch=getchar();
map[i][++j]=ch;
if(ch=='O')
x=i,y=j;
if(ch=='X')
ex=i,ey=j;
cover(trans(ch),i,j,1);//覆盖
if(j!=n)
--i;
else
j=0;//结束本行读入
}
if(ban[x][y])
{
puts("-1");
continue;
}
reg int res=1;
for(;res<=500;++res)//IDDFS
{
if(dfs(res,x,y))
break;
}
printf("%d\n",res==500?-1:res);
}
return(0);
}