題目大意:在一個8*8的棋盤裏有一個國王和一些騎士,我們須要把他們送到同一頂點上去,騎士和國王的行動方式如圖所看到的。國王能夠選擇一名騎士作爲坐騎。上馬後相當和該騎士
一起行動(相當於一個騎士),同一位置能夠同一時候有多個騎士和國王。問最少走的步數
解題思路:把8*8棋盤變成0~63的數,Floyd求出隨意兩點之間的最短路徑。8*8枚舉就可以。枚舉終點,騎士上馬點,國王上哪個騎士,終於負責度O(64^4)。
#include <string.h>
#include <algorithm>
#include <iostream>
#include <stdio.h>
using namespace std;
char s[105];
int cx[8][2]= {{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
int dx[8][2]= {{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
int a[65][65],b[65][65],rking[65],king;
bool judge(int i,int j)
{
if(i>=0&&i<8&&j>=0&&j<8)
return true;
return false;
}
void init()
{
for(int i=0; i<64; i++)
{
for(int j=0; j<64; j++)
{
if(i==j)
a[i][j]=b[i][j]=0;
else
a[i][j]=b[i][j]=999;
}
}
for(int i=0; i<8; i++)
{
for(int j=0; j<8; j++)
{
for(int k=0; k<8; k++)
{
int x=i+cx[k][0];
int y=j+cx[k][1];
int xx=i+dx[k][0];
int yy=j+dx[k][1];
if(judge(x,y))
{
a[i+j*8][x+y*8]=1;
}
if(judge(xx,yy))
{
b[i+j*8][xx+yy*8]=1;
}
}
}
}
for(int k=0; k<64; k++)
{
for(int i=0; i<64; i++)
{
for(int j=0; j<64; j++)
{
a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
b[i][j]=min(b[i][j],b[i][k]+b[k][j]);
}
}
}
}
int main()
{
init();
while(~scanf("%s",s))
{
int n=strlen(s);
king=s[0]-'A'+(s[1]-'1')*8;
int cnt=0;
for(int i=2; i<n; i+=2)
{
int x=s[i+1]-'1';
int y=s[i]-'A';
rking[cnt++]=x*8+y;
}
int ans=9999999;
for(int i=0;i<64;i++)///終點
{
for(int j=0;j<64;j++)///國王上馬點
{
for(int k=0;k<cnt;k++)///國王所上的騎士
{
int sum=0;
for(int l=0;l<cnt;l++)
{
if(l==k)continue;
sum+=a[rking[l]][i];
}
sum+=b[king][j]+a[rking[k]][j]+a[j][i];
ans=min(ans,sum);
}
}
}
printf("%d\n",ans);
}
return 0;
}