本来这是个简单题,但是两年前第一次做的时候发现它真的太经典了!
【camelot】
/*
ID: wangqia6
TASK: camelot
LANG: C++
*/
#include <fstream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const long INF = 0x01010100;
const long NMAX = 30;
const long CMAX = 900;
const long KMAX = 8;
const long WMAX = 16;
const long dx[KMAX] = {1,2,-1,-2,-2,1,2,-1};
const long dy[KMAX] = {2,1,-2,-1,1,-2,-1,2};
const long cx[KMAX] = {1,-1,1,-1,0,0,1,-1};
const long cy[KMAX] = {1,-1,-1,1,1,-1,0,0};
const long ex[WMAX] = {2,-2,2,-2,0,0,2,-2,2,2,1,-1,-2,-2,1,-1};
const long ey[WMAX] = {2,-2,-2,2,2,-2,0,0,1,-1,2,2,1,-1,-2,-2};
const long A = long('A') - 1;
struct posi
{
long x,y;
};
ifstream fin ("camelot.in");
ofstream fout ("camelot.out");
long n,m,knight_sum = 0,pick_sum = 0,pick_two_sum = 0,
dist[NMAX][NMAX][NMAX][NMAX],dist_sum,ans = INF;
bool vis[NMAX][NMAX];
posi meet,king,knight[CMAX],pick[KMAX],pick_two[WMAX];
queue<long> quex,quey;
void initdata()
{
char ch;
long t;
fin >> n >> m;
fin >> ch >> king.y;
king.x = long(ch) - A;
while (fin >> ch >> t)
{
knight[knight_sum].x = long(ch) - A;
knight[knight_sum].y = t;
knight_sum++;
}
return;
}
bool check(long a,long b)
{
if (a < 1)
return false;
if (b < 1)
return false;
if (a > m)
return false;
if (b > n)
return false;
return true;
}
void get_dist(long sx, long sy)
{
long tx,ty,i,px,py,dd;
memset(vis,0,sizeof(vis));
vis[sx][sy] = true;
dist[sx][sy][sx][sy] = 0;
quex.push(sx);
quey.push(sy);
while (! quex.empty())
{
tx = quex.front();
ty = quey.front();
dd = dist[sx][sy][tx][ty];
for (i = 0; i < KMAX; i++)
{
px = tx + dx[i];
py = ty + dy[i];
if (check(px,py) && (! vis[px][py]))
{
vis[px][py] = true;
dist[sx][sy][px][py] = dd + 1;
quex.push(px);
quey.push(py);
}
}
quex.pop();
quey.pop();
}
return;
}
void calc_dist()
{
long i,j;
memset(dist,0x0f,sizeof(dist));
for (i = 1; i <= m; i++)
for (j = 1; j <= n; j++)
get_dist(i,j);
return;
}
long king_dist(long i,long j)
{
return max(abs(king.x - i),abs(king.y - j));
}
void solve()
{
long i,j,new_dist;
for (i = 0; i < KMAX; i++)
if (check(king.x + cx[i],king.y + cy[i]))
{
pick[pick_sum].x = king.x + cx[i];
pick[pick_sum].y = king.y + cy[i];
pick_sum++;
}
for (i = 0; i < WMAX; i++)
if (check(king.x + ex[i],king.y + ey[i]))
{
pick_two[pick_two_sum].x = king.x + ex[i];
pick_two[pick_two_sum].y = king.y + ey[i];
pick_two_sum++;
}
for (meet.x = 1; meet.x <= m; meet.x++)
for (meet.y = 1; meet.y <= n; meet.y++)
{
dist_sum = 0;
for (i = 0; i < knight_sum; i++)
{
dist_sum += dist[meet.x][meet.y][knight[i].x][knight[i].y];
if (dist_sum > ans)
break;
}
if (dist_sum > ans)
continue;
if (dist_sum + king_dist(meet.x,meet.y) < ans)
ans = dist_sum + king_dist(meet.x,meet.y);
for (j = 0; j < knight_sum; j++)
{
new_dist = dist_sum - dist[knight[j].x][knight[j].y][meet.x][meet.y] +
dist[knight[j].x][knight[j].y][king.x][king.y] +
dist[king.x][king.y][meet.x][meet.y];
if (new_dist < ans)
ans = new_dist;
}
for (i = 0; i < pick_sum; i++)
for (j = 0; j < knight_sum; j++)
{
new_dist = dist_sum - dist[knight[j].x][knight[j].y][meet.x][meet.y] +
dist[knight[j].x][knight[j].y][pick[i].x][pick[i].y] +
1 + dist[pick[i].x][pick[i].y][meet.x][meet.y];
if (new_dist < ans)
ans = new_dist;
}
for (i = 0; i < pick_two_sum; i++)
for (j = 0; j < knight_sum; j++)
{
new_dist = dist_sum - dist[knight[j].x][knight[j].y][meet.x][meet.y] +
dist[knight[j].x][knight[j].y][pick_two[i].x][pick_two[i].y] +
2 + dist[pick_two[i].x][pick_two[i].y][meet.x][meet.y];
if (new_dist < ans)
ans = new_dist;
}
}
}
void outitdata()
{
fout << ans << endl;
fin.close();
fout.close();
}
int main()
{
initdata();
calc_dist();
solve();
outitdata();
return 0;
}