题意:
棋盘上有一些骑士和一个王 王在移动时与骑士相遇可以同行 问 最少多少步可以使骑士和王汇聚到一起
思路:
先假设棋盘上每个点都有个骑士 bfs得出任意两点的最短路 再枚举终点 分两种情况讨论:
1.王和骑士均自己走到终点
2.骑士去接王一起走
对于情况1直接计算即可 对于情况2需要枚举哪个骑士在哪个点接上王
但完全枚举数量太大需要剪枝——王最多移动两步
代码:
/*
ID: housera1
PROG: camelot
LANG: C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int dp[31][27][31][27];
int dir[8][2]={ {-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2} };
int n,m,ans=2147483647,tot;
struct node
{
int x,y;
}kt[810],kg,u,v;
queue<node> qu;
void bfs(int sx,int sy)
{
int i;
while(!qu.empty()) qu.pop();
u.x=sx; u.y=sy;
qu.push(u);
while(!qu.empty())
{
u=qu.front();
qu.pop();
for(i=0;i<8;i++)
{
v.x=u.x+dir[i][0]; v.y=u.y+dir[i][1];
if(v.x>=1&&v.x<=n&&v.y>=1&&v.y<=m&&(dp[sx][sy][v.x][v.y]==-1||dp[sx][sy][v.x][v.y]>dp[sx][sy][u.x][u.y]+1))
{
if(dp[sx][sy][v.x][v.y]==-1) qu.push(v);
dp[sx][sy][v.x][v.y]=dp[sx][sy][u.x][u.y]+1;
}
}
}
}
void make_dp()
{
int i,j;
memset(dp,-1,sizeof(dp));
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
dp[i][j][i][j]=0;
bfs(i,j);
}
}
/*
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
printf("(1,25)->(%-2d,%-2d) dp %d\n",i,j,dp[i][j][1][25]);
}
}
*/
}
void solve()
{
int i,j,k,l,o,p,tmp;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
for(l=max(1,kg.x-2);l<=min(n,kg.x+2);l++)
{
for(o=max(1,kg.y-2);o<=min(m,kg.y+2);o++)
{
for(k=0,tmp=max(abs(kg.x-l),abs(kg.y-o));k<tot;k++)
{
if(dp[kt[k].x][kt[k].y][i][j]==-1) break;
else tmp+=dp[kt[k].x][kt[k].y][i][j];
}
if(k!=tot) continue;;
for(k=0;k<tot;k++)
{
p=tmp;
p-=dp[kt[k].x][kt[k].y][i][j];
if(dp[l][o][i][j]==-1||dp[kt[k].x][kt[k].y][l][o]==-1) break;
p+=dp[l][o][i][j]+dp[kt[k].x][kt[k].y][l][o];
ans=min(ans,p);
//printf("end (%d,%d) mid (%d,%d) tmp %d\n",i,j,l,o,p);
}
}
}
}
}
printf("%d\n",ans);
}
int main(){
int Debug=0;
if(!Debug){
freopen("camelot.in","r",stdin);
freopen("camelot.out","w",stdout);
}
int i=0,j;
char input[5];
scanf("%d%d",&n,&m);
scanf("%s%d",input,&j);
kg.y=input[0]-'A'+1; kg.x=j;
while(~scanf("%s%d",input,&j))
{
kt[i].y=input[0]-'A'+1;
kt[i].x=j;
i++;
}
tot=i;
if(tot==0)
{
printf("0\n");
return 0;
}
make_dp();
solve();
return 0;
}