Cod sursa(job #12215)

Utilizator MariusMarius Stroe Marius Data 3 februarie 2007 12:00:52
Problema A+B Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.21 kb
#include <cstdio>
#include <memory>
using namespace std;

const char iname[] = "arthur.in";
const char oname[] = "arthur.out";

#define MAX_N 207
#define MAX_P 107
#define INF   int(1e9)
#define code(i, j)   ((i) * (N) + (j))
#define inside(i, j) (((i) >= 0) && ((j) >= 0) && ((i) < (M)) && ((j) < (N)))

int M, N, K, P;

int XA, YA, XC, YC;

int xy[MAX_P][2];	/* hanurile */

int H[MAX_N][MAX_N];	/* indicele hanului */

int D[MAX_P][MAX_P];

int A[MAX_N][MAX_N];

int E[MAX_N][MAX_N];

int Z[MAX_N][MAX_N];

int T[131072], R[131072];


void read_in(void)
{
	freopen(iname, "r", stdin);
	int i;
	scanf("%d %d %d %d", & M, & N, & K, & P);
	scanf("%d %d", & XA, & YA);
	scanf("%d %d", & XC, & YC);
	XA --, YA --;
	XC --, YC --;
	for (i = 1; i <= P; ++i) {
		scanf("%d %d", xy[i], xy[i] + 1);
		xy[i][0] --;
		xy[i][1] --;
		H[ xy[i][0] ][ xy[i][1] ] = i;
	}
	P ++;
	xy[P][0] = XC;
	xy[P][1] = YC;
	H[XC][YC] = P;
}

int dxl[] = {-2, -1, +1, +2, +2, +1, -1, -2};

int dyl[] = {+1, +2, +2, +1, -1, -2, -2, -1};

int Q[MAX_N * MAX_N];

void dolee(const int num)
{
	int x = xy[num][0];
	int y = xy[num][1];
	int l, r;
	int i, j, k;
	for (i = 0; i < M; ++i)
		for (j = 0; j < N; ++j)	  A[i][j] = INF;
	A[x][y] = 0;
	for (Q[l = r = 0] = code(x, y); l <= r; ++l) {
		x = Q[l] / N;
		y = Q[l] % N;
		if (A[x][y] == K)
			break ;
		for (k = 0; k < 8; ++k) {
			i = x + dxl[k];
			j = y + dyl[k];
			if (inside(i, j) && (A[i][j] > A[x][y] + 1))
				A[i][j] = A[x][y] + 1, Q[++ r] = code(i, j);
		}
	}
	for (k = num + 1; k <= P; ++k)
		D[num][k] = D[k][num] = A[ xy[k][0] ][ xy[k][1] ];
}

void buildTree(int n, int lo, int hi)
{
	int mid = (hi + lo) / 2;
	T[n] = INF;
	if (hi == lo)
		return ;
	buildTree(2 * n, lo, mid);
	buildTree(2 * n + 1, mid + 1, hi);
}

void update(int n, int lo, int hi, int ind, int val)
{
	int mid = (hi + lo) / 2;
	if (hi == lo) {
		T[n] = val;
		R[n] = ind;
		return ;
	}
	if (ind <= mid)
		update(2 * n, lo, mid, ind, val);
	else
		update(2 * n + 1, mid + 1, hi, ind, val);
	T[n] = T[2 * n];
	R[n] = R[2 * n];
	if (T[n] > T[2 * n + 1])
		T[n] = T[2 * n + 1], R[n] = R[2 * n + 1];
}

void print_road_to_han(const int a, const int b)
{
	int x = xy[a][0];
	int y = xy[a][1];
	int i;
	int j;
	int k;
	int l, r;
	for (i = 0; i < M; ++i)
		for (j = 0; j < N; ++j)	 A[i][j] = INF;
	A[x][y] = 0;
	for (Q[l = r = 0] = code(x, y); l <= r; ++l) {
		x = Q[l] / N;
		y = Q[l] % N;
		for (k = 0; k < 8; ++k) {
			i = x + dxl[k];
			j = y + dyl[k];
			if (inside(i, j) && (A[i][j] == INF))
				A[i][j] = code(x, y), Q[++ r] = code(i, j);
		}
		if (A[ xy[b][0] ][ xy[b][1] ] < INF)
			break ;
	}
	x = xy[b][0];
	y = xy[b][1];
	for (; A[x][y] > 0; ) {
		i = x;
		j = y;
		x = A[i][j] / N;
		y = A[i][j] % N;
		if (A[x][y] > 0)
			printf("%d %d\n", x + 1, y + 1);
	}
}

void print_out(int i, int j)
{
	if (Z[i][j] > 0) {
		int x = Z[i][j] / N;
		int y = Z[i][j] % N;
		print_out(x, y);
		if (H[x][y] > 0 && H[i][j] > 0)
			print_road_to_han(H[i][j], H[x][y]);
	}
	printf("%d %d\n", i + 1, j + 1);
}

int main(void)
{
	read_in();
	int i;
	int j;
	int stp;
	int lo = 0;
	int hi = M * N - 1;
	int dx[] = {-1, -1, 0, +1, +1, +1, 0, -1};
	int dy[] = {0, +1, +1, +1, 0, -1, -1, -1};
	for (i = 1; i < P; ++i)
		dolee(i);
	buildTree(1, lo, hi);
	for (i = 0; i < M; ++i)
		for (j = 0; j < N; ++j)	 A[i][j] = INF;
	
	A[XA][YA] = 0;
	update(1, lo, hi, code(XA, YA), 0);
	for (stp = lo; stp < hi; ++stp) {
		int x = R[1] / N;
		int y = R[1] % N;
		int d = A[x][y];
		E[x][y] = 1, update(1, lo, hi, R[1], INF);
		if (H[x][y] > 0) {
			int num = H[x][y];
			for (int k = 1; k <= P; ++k) {
				i = xy[k][0];
				j = xy[k][1];
				if ((E[i][j] == 0) && (D[num][k] <= K) && (A[i][j] > d + D[num][k])) {
					update(1, lo, hi, code(i, j), A[i][j] = d + D[num][k]);
					Z[i][j] = code(x, y);
				}
			}
		}
		for (int k = 0; k < 8; ++k) {
			i = x + dx[k];
			j = y + dy[k];
			if (inside(i, j) && (E[i][j] == 0) && (A[i][j] > d + 1)) {
				update(1, lo, hi, code(i, j), A[i][j] = d + 1);
				Z[i][j] = code(x, y);
			}
		}
	}
	freopen(oname, "w", stdout);
	printf("%d\n", A[XC][YC]);
	print_out(XC, YC);
	return 0;
}