题意:把这些所有的棋子移动到一个点,king可以自己走或者骑马走。
思路:预处理,枚举所有的点作为他们的集合点。。
先计算马走的步数,再计算king到最近马路的步数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
using namespace std;
const int N = 8;
int re[N][N][N][N];
queue<int> que;
bool inline oor(int x,int y)
{
if(x<0||x>=8) return false;
if(y<0||y>=8) return false;
return true;
}
int dx[] = {-2,-2,-1,-1,1,1,2,2};
int dy[] = {1,-1,2,-2,2,-2,1,-1};
void mindis(int x,int y)
{
while(!que.empty()) que.pop();
que.push((x<<5)|y);
re[x][y][x][y] = 0;
int e,ex,ey,tx,ty;
while(!que.empty())
{
e = que.front(); que.pop();
ex = e>>5;ey = e&15;
for(int i=0;i<8;i++)
{
tx = ex+dx[i],ty=ey+dy[i];
if((!oor(tx,ty))||(re[x][y][tx][ty]!=-1)) continue;
re[x][y][tx][ty] = re[x][y][ex][ey]+1;
que.push(tx<<5|ty);
}
}
}
void init()
{
memset(re,-1,sizeof(re));
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
mindis(i,j);
}
char ch[256];
bool visit[8][8];
struct nod{
int x,y,dis;
};
queue <nod> qq;
int dxx[]={0,0,1,1,1,-1,-1,-1};
int dyy[]={-1,1,-1,0,1,-1,0,1};
int kinv[8][8];
int oper(int x,int y)
{
memset(visit,0,sizeof(visit));
visit[x][y] = 1;
while(!qq.empty()) qq.pop();
nod e,t;
int len = strlen(ch);
int ret = 0;
for(int i=2;i<len;i+=2)
{
e.x = ch[i]-'A';e.y= ch[i+1]- '1';
e.dis = re[x][y][e.x][e.y];
qq.push(e);
visit[e.x][e.y] = 1;
ret+=e.dis;
}
int tx,ty;
while(!qq.empty())
{
e = qq.front();qq.pop();
for(int i=0;i<8;i++)
{
tx=e.x+dx[i],ty=e.y+dy[i];
if((!oor(tx,ty))||visit[tx][ty]||(re[x][y][tx][ty]!=e.dis-1)) continue;
t.x = tx,t.y = ty;t.dis=e.dis-1;
visit[tx][ty] = 1;
qq.push(t);
}
}
while(!que.empty()) que.pop();
que.push((ch[0]-'A')<<5|(ch[1]-'1'));
memset(kinv,0,sizeof(kinv));
kinv[ch[0]-'A'][ch[1]-'1'] = 1;
while(!que.empty())
{
int ee = que.front();que.pop();
int ex = ee>>5,ey = ee&15;
if(visit[ex][ey]) {
return ret+ kinv[ex][ey] -1;
}
for(int i=0;i<8;i++)
{
int tx = ex+dxx[i],ty=ey+dyy[i];
if(!oor(tx,ty)||kinv[tx][ty]) continue;
kinv[tx][ty] = kinv[ex][ey]+1;
que.push(tx<<5|ty);
}
}
return 100;
}
void solve()
{
int ans = 10000000;
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
ans = min(ans,oper(i,j));
printf("%d\n",ans);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
init();
scanf("%s",ch);
solve();
return 0;
}