Cod sursa(job #254435)

Utilizator savimSerban Andrei Stan savim Data 7 februarie 2009 12:06:41
Problema Kdrum Scor 20
Compilator cpp Status done
Runda Stelele Informaticii 2009, clasele 9-10, ziua 2 Marime 3 kb
#include <stdio.h>
#include <algorithm>

using namespace std;

#define MAX_L 60
#define MAX_D 510

int i, j, n, m, k, x1, y1, x2, y2, p, ind, st, dr, sol, cop, nr;
int divi[MAX_D];
int a[MAX_L][MAX_L], dist[MAX_L][MAX_L], cules[MAX_L][MAX_L];
int c[MAX_L][MAX_L][MAX_D];
int lee[MAX_L * MAX_L][2];
int fprim[MAX_L], put[MAX_L], factor[MAX_L];
int ver[4] = {0, 0, -1, 1};
int ori[4] = {-1, 1, 0, 0};

struct elem {
	int x;
	int y;
} v[MAX_L * MAX_L];

int cmmdc(int p, int q) {
	int a = p, b = q, r = 0;
	
	while (a % b != 0) {
		r = a % b;
		a = b;
		b = r;
	}
	return b;
}

int numar(int p) {
	int rez = 1, cop = p;
	for (int i = 1; i <= nr; i++)
		if (p % factor[i] == 0) rez *= factor[i];
		else while (cop % fprim[i] == 0) {
				rez *= fprim[i];
				cop /= fprim[i];
		     }
	return rez;
}

inline int cmp(elem a, elem b) {
	return c[a.x][a.y][divi[p]] < c[b.x][b.y][divi[p]];
}

void funct_lee(int poz) {
	st = 0; dr = 1;
	lee[dr][0] = v[poz].x;
	lee[dr][1] = v[poz].y;
	
	for (int i = 0; i <= n; i++)
		for (int j = 0; j <= m; j++)
			dist[i][j] = cules[i][j] = 0;
	cules[v[poz].x][v[poz].y] = 1;
	
	while (st + 1 <= dr) {
		st++;
		for (int i = 0; i < 4; i++) {
			int xn = lee[st][0] + ver[i];
			int yn = lee[st][1] + ori[i];
			
			if (xn == x2 && yn == y2 && c[v[poz].x][v[poz].y][divi[p]] + dist[lee[st][0]][lee[st][1]] + 1 < sol && divi[p] == k)
				sol = c[v[poz].x][v[poz].y][divi[p]] + dist[lee[st][0]][lee[st][1]] + 1;
			
			if (a[xn][yn] != 0 && dist[xn][yn] == 0 && (!(xn == v[poz].x && yn == v[poz].y))) {
				cules[xn][yn] = numar(cules[lee[st][0]][lee[st][1]] * a[xn][yn]);
				dist[xn][yn] = dist[lee[st][0]][lee[st][1]] + 1;
				lee[++dr][0] = xn;
				lee[dr][1] = yn;
				
				if (a[xn][yn] != 0 && a[xn][yn] != 1) {
					int alfa = numar(cules[xn][yn] * divi[p]);
					if (c[xn][yn][alfa] == 0 || 
						c[xn][yn][alfa] > c[v[poz].x][v[poz].y][divi[p]] + dist[xn][yn]) 
						c[xn][yn][alfa] = c[v[poz].x][v[poz].y][divi[p]] + dist[xn][yn];
				}
			}
		}
	}
}

int main() {

	freopen("kdrum.in", "r", stdin);
	freopen("kdrum.out", "w", stdout);
	
	scanf("%d %d %d", &n, &m, &k);
	scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
	for (i = 1; i <= n; i++)
		for (j = 1; j <= m; j++) {
			scanf("%d", &a[i][j]);
			if (a[i][j]) a[i][j] = cmmdc(a[i][j], k);
		}
	
	cop = k;
	for (i = 1; i <= k; i++) {
		if (k % i == 0) divi[++divi[0]] = i;
		if (i != 1 && cop % i == 0) {
			fprim[++nr] = i;
			factor[nr] = 1;
		}
		while (cop % i == 0 && i != 1) {
			cop /= i;
			factor[nr] *= i;
			put[nr]++;
		}
	}
	
	c[x1][y1][a[x1][y1]] = 1; sol = (1 << 30);
	for (p = 1; p <= divi[0]; p++) {
		ind = 0;
		for (i = 1; i <= n; i++)
			for (j = 1; j <= m; j++)
				if (c[i][j][divi[p]]) {
					ind++;
					v[ind].x = i;
					v[ind].y = j;
				}
		sort(v + 1, v + ind + 1, cmp);
		
		for (i = 1; i <= ind; i++)
			funct_lee(i);
	}
	if (c[x2][y2][k] < sol && c[x2][y2][k] != 0) sol = c[x2][y2][k];
	printf("%d\n", sol);
	
	return 0;
}