这道题目确实是挺难想的——对于我而言,如果不看别人的思路,我也是想不出的。
我现在采用的思路是:
枚举国王和骑士们相遇的地点(最多26*30),及可能会带上国王的好心骑士及他们相遇的地点(坐标)。
呵呵……这就得想明白一点,如下图所示
如果某个骑士要去接国王,那么应该这个骑士应到国王附近一格距离(图中蓝色部分)或国王当前所在坐标位置(图中红色部分)。
当然也要考虑国王自己跑到终点的情况。
下面是我代码,仅供参考:
/*
ID: guo geer
PROG: camelot
LANG: C++
*/
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<fstream>
#include<cmath>
using namespace std;
int kingMove [9][2] = {{0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 0}};
int knightMove [8][2] = {{1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}, {-2, 1}, {-1, 2}};
int dist[27][31][27][31];
int knightLocation[2000][2];
void bfs(int board[][31], int x0, int y0, int X, int Y)
{
int f, r, r1;
int q[10000][2];
q[0][0] = x0, q[0][1] = y0;
board[x0][y0] = 0;
f=r=r1=0;
int steps = 1;
while(true)
{
r ++;
while(f != r)
{
int x, y;
for(int i=0; i<8; i++)
{
x = q[f][0]+knightMove[i][0];
y = q[f][1]+knightMove[i][1];
if(x>0 && x<=X && y>0 && y<=Y && board[x][y] == -1)
{
q[++r1][0] = x;
q[r1][1] = y;
board[x][y] = steps;
}
}
f++;
}
steps ++;
if(r1 < r) return ;
r = r1;
}
}
int main()
{
freopen("camelot.in", "r", stdin);
freopen("camelot.out", "w", stdout);
int x0, y0, X, Y;
char ch;
scanf("%d %d", &Y, &X);
scanf(" %c %d", &ch, &y0);
x0 = ch-'A'+1;
memset(dist, -1, sizeof(dist));
for(int i=1; i<=X; i++)
for(int j=1; j<=Y; j++) bfs(dist[i][j], i, j, X, Y);
int x, y;
int n = 0;
while(scanf(" %c %d", &ch, &y) != EOF)
{
x = ch-'A'+1;
knightLocation[n][0] = x;
knightLocation[n][1] = y;
n ++;
}
int res = 1000000;
for(int i=1; i<=X; i++)
{
for(int j=1; j<=Y; j++)
{
int s0 = 0;
int isAllPositive = 1;
for(int k=0; k<n; k++)
{
int tx, ty;
tx = knightLocation[k][0];
ty = knightLocation[k][1];
s0 += dist[i][j][tx][ty];
if(dist[i][j][tx][ty] < 0) isAllPositive = 0;
}
if(isAllPositive == 0) continue;
for(int k=0; k<n; k++)
{
int tx, ty;
tx = knightLocation[k][0];
ty = knightLocation[k][1];
for(int dir=0; dir<9; dir++)
{
int x1 = kingMove[dir][0]+x0;
int y1 = kingMove[dir][1]+y0;
if(x1 < 1 || x1 > X || y1 < 1 || y1 > Y) continue;
if(dist[i][j][tx][ty] < 0 || dist[i][j][x1][y1] < 0 || dist[x1][y1][tx][ty] < 0) continue;
int s = s0 - dist[i][j][tx][ty] + dist[i][j][x1][y1] + dist[x1][y1][tx][ty];
if(dir != 8) s ++;
if(res > s) res = s;
}
if(res > max(abs(x0-tx),abs(y0-ty))+s0) res = max(abs(x0-tx),abs(y0-ty))+s0;
}
}
}
if(n == 0) res = 0;
printf("%d\n", res);
return 0;
}