Cod sursa(job #654122)

Utilizator mihaibogdan10Mihai Bogdan mihaibogdan10 Data 29 decembrie 2011 17:06:11
Problema Kdrum Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.79 kb
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;

struct cell	{int x, y, lng, poz;};
int map[51][51], dist[51][51][400], K, N, M;
queue <cell> q;
vector <int> Div;

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

void DescompunePeK(){
	for (int i = 1; i <= K; i++)
		if (K % i == 0) Div.push_back(i);
}

int Poz(int divizor){
	int st = 0, dr = Div.size() - 1, m;
	
	while (st <= dr){
		m = (st + dr) / 2;
		if (Div[m] == divizor) return m;
		else if(Div[m] > divizor) dr = m - 1;
		else st = m + 1;
	}
}

int main(){
	freopen("kdrum.in", "r", stdin), freopen("kdrum.out", "w", stdout);
	int x1, y1, x2, y2, i, j, p, x, y, x0, y0, factor0, lng, factor, poz;
	int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
	scanf("%d %d %d %d %d %d %d", &N, &M, &K, &x1, &y1, &x2, &y2);
	
	for (i = 1; i <= N; i++)
		for (j = 1; j <= M; j++) scanf("%d", &map[i][j]); 
	
	for (i = 1; i <= N; i++)
		for (j = 1; j <= M; j++) 
			for (p = 0; p <= 400; p++) dist[i][j][p] = 0xfffffff;
	DescompunePeK();
	
	//dist[x][y][z] = lungimea minima a drumurilor care pana la divizibilitatea prin 
	//K mai au nevoie de al z-lea divizor al lui K si se incheie pe poz x,y
	
	q.push((cell){x1, y1, 1, Poz(K / CMMDC(K, map[x1][y1]))});
	while(!q.empty()){
		x0 = q.front().x, y0 = q.front().y, factor0 = Div[q.front().poz], lng = q.front().lng + 1;
		q.pop();
		
		for (i = 0; i < 4; i++){
			x = x0 + dx[i], y = y0 + dy[i];			
			if (0 < x && x <= N && 0 < y && y <= M && map[x][y]){
				factor = factor0 / CMMDC(factor0, map[x][y]);
				poz = Poz(factor);
				
				if (lng < dist[x][y][poz]){
						dist[x][y][poz] = lng;
						q.push((cell){x, y, lng, poz});
				}
			}
		}
	}
	
	printf("%d\n", dist[x2][y2][0]);
	return 0;
}