Cod sursa(job #1221808)

Utilizator ion824Ion Ureche ion824 Data 21 august 2014 15:05:01
Problema Barbar Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.48 kb
#include<cstdio>
#include<algorithm>
#define GOL '.'
#define DRAGON 'D'
#define START 'I'
#define FINISH 'O'
#define WALL '*'
#define NM 1003
#define INF 0x3f3f3f3f
using namespace std;
const int dx[4] = {-1, 0, 0, 1};
const int dy[4] = {0, -1, 1, 0};

char a[NM][NM];
bool viz[NM][NM];
int d[NM][NM],g[NM][NM];
int X1[NM],X2[NM],Y1[NM],Y2[NM],hp;

typedef struct tr{
	int i,j,dist;
}TRIO;
TRIO h[NM];

void upheap(int k){
	while(k>1 && h[k].dist > h[k/2].dist)
	{
		swap(h[k],h[k/2]);
		k /= 2;
	}
}

void downheap(int k){
	int nod = 1;
	
	while(nod)
	{
		nod = 0;
		if(k + k <= hp)
		{
			nod = k + k;
			if(nod < hp && h[nod+1].dist > h[nod].dist) nod++;
			if(h[nod].dist <= h[k].dist) nod = 0;
			if(nod)
			{
				swap(h[k],h[nod]);
				k = nod;
			}
		}
	}
}


int main(){
	freopen("barbar.in","r",stdin);
	freopen("barbar.out","w",stdout);
	int N,M,k,kk,i,j,t;
	int SX,SY,FX,FY,DX,DY;
	
	scanf("%d%d\n",&N,&M);
	
	for(i=1;i<=N;++i) scanf("%s",a[i]+1);
	
	k = 0;
	int *x1, *x2, *y1, *y2;
	x1 = X1; x2 = X2;
	y1 = Y1; y2 = Y2;
	
	for(i=1;i<=N;++i)
	  for(j=1;j<=M;++j)
	  {
	  	if(a[i][j] == DRAGON)
	  	{
	  		++k;
	  		x1[k] = i; 
	  		y1[k] = j;
	  	}
	  	if(a[i][j] == START)
	  	{
	  		SX = i;
	  		SY = j;
	  	}
	  	if(a[i][j] == FINISH)
	  	{
	  		FX = i;
	  		FY = j;
	  	}
	  	
	  	d[i][j] = INF;
	  }
	
	
	for(i=1;i<=k;++i) d[x1[i]][y1[i]] = 0;
	
	while(k>0)
	{
		kk = 0;
		for(i=1;i<=k;++i)
		{
			for(t=0;t<4;++t)
			{
				DX = x1[i] + dx[t]; DY = y1[i] + dy[t];
				if(a[DX][DY] == WALL || DX > N || DY > M || DX<1 || DY<1) continue;
				if(d[DX][DY] <= d[x1[i]][y1[i]] + 1) continue;
				
				d[DX][DY] = d[x1[i]][y1[i]] + 1;
				x2[++kk] = DX;
				y2[kk] = DY;	
			}
		}
		
		k = kk;
		swap(x1,x2);
		swap(y1,y2);
	}
		
	hp = 1;
	h[1].i = SX; h[1].j = SY; h[1].dist = d[SX][SY];
	viz[SX][SY] = 1; g[SX][SY] = d[SX][SY];
	
	int x,y,dst;
	
	while(hp>0)
	{
		x = h[1].i; y = h[1].j; dst = h[1].dist;
		if(hp>1)
		{
		  swap(h[1],h[hp]);
		  -- hp;
		  downheap(1);	
		}
		else --hp;
		
		for(t=0;t<4;++t)
		{
			DX = x + dx[t]; DY = y + dy[t];
			if(viz[DX][DY] || DX<1 || DY<1 || DX > N || DY > M || a[DX][DY] == WALL) continue;
			
			viz[DX][DY] = 1;
			g[DX][DY] = min(dst, d[DX][DY]);
			++hp;
			h[hp].i = DX;
			h[hp].j = DY;
			h[hp].dist = g[DX][DY];
			upheap(hp);
		}	
	}
	
	if(!viz[FX][FY]) printf("-1\n");
	else printf("%d\n",g[FX][FY]);
	
	return 0;
}