Cod sursa(job #53283)

Utilizator randommanThe Randomizer randomman Data 21 aprilie 2007 18:23:19
Problema Barbar Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.75 kb
/* Ivan Nicolae - Bucuresti*/
#include <stdio.h>
#include <string.h>

#define NMAX 1001
#define Infinity 0x3f3f3f3f
#define _fin "barbar.in"
#define _fout "barbar.out"
#define min(a,b) (((a) > (b)) ? (b) : (a))

int i,j,n,m,D[NMAX][NMAX], A[NMAX][NMAX], c1, c2, sx, sy, fx, fy;
int c1_x[NMAX*NMAX],c1_y[NMAX*NMAX],c2_x[NMAX*NMAX],c2_y[NMAX*NMAX];
char H[NMAX][NMAX];

int dx[]={-1,+0,+1,-0};
int dy[]={-0,+1,+0,-1};
/* D[i][j] = distanta din pucntul (i,j) pan' la cel mai apropriat dragon
   A[i][j] = distanta minima din distantele pan la cel mai pr dragon de pe drumul pan' in
             punctul (i,j)
   H[i][j] = harta (I,O,D, ,* )*/

void Repart(int x, int y, char c)
{
 if (c=='I')
   { sx=x; sy=y; }

 if (c=='O')
   { fx=x; fy=y; }

 if (c=='D')
   { c1_x[++c1]=x; c1_y[c1]=y; }
}

void ReadData(void)
{
 int i,j; char lne;
 freopen(_fin,"r",stdin);
 scanf("%d%d%c",&n,&m,&lne);
 for (i=1;i<=n;i++)
    {
     for (j=1;j<=m;j++)
        {
         scanf("%c",&H[i][j]);
         Repart(i,j,H[i][j]);
        }
     scanf("%c",&lne);
    }
 fclose(stdin);
}

int Okay(int x, int y)
{
 if (x < 1 || x > n || y < 1 || y > m)
   return 0;
 if (H[x][y] == '*')
   return 0;
 return 1;
}

void Relax_D(int x, int y)
{
 int i;
 for (i=0;i<=3;i++)
    {
     int xx=x+dx[i], yy=y+dy[i];
     if (Okay(xx,yy))
       {
        if (D[xx][yy] > D[x][y] + 1)
          {
           D[xx][yy] = D[x][y] + 1;
           c2_x[++c2]=xx; c2_y[c2]=yy;
          }
       }
    }
}

void FindDToNearestDragon(void)
{
 int i;
 memset(D,Infinity,sizeof(D));
 for (i=1;i<=c1;i++)
    D[c1_x[i]][c1_y[i]]=0;
 
 while (c1)
      {
       c2=0;
       for (i=1;i<=c1;i++)
          Relax_D(c1_x[i],c1_y[i]);
       memcpy(c1_x,c2_x,sizeof(c2_x));
       memcpy(c1_y,c2_y,sizeof(c2_y));
       c1=c2;
      }
}

void Relax_P(int x, int y)
{
 int i;
 for (i=0;i<=3;i++)
    {
     int xx=x+dx[i], yy=y+dy[i];
     if (Okay(xx,yy))
       {
        if (min(D[xx][yy],A[x][y]) > A[xx][yy])
          {
           A[xx][yy]=min(D[xx][yy],A[x][y]);
           c2_x[++c2]=xx; c2_y[c2]=yy;
          }
       }
    }
}

void Bellman_Ford(void)
{
 int i;
 c1=0; c2=0;
 memset(A,-Infinity,sizeof(A));
 c1_x[++c1]=sx; c1_y[c1]=sy; A[sx][sy]=D[sx][sy];

 while (c1)
      {
       c2=0;
       for (i=1;i<=c1;i++)
          Relax_P(c1_x[i],c1_y[i]);
       memcpy(c1_x,c2_x,sizeof(c2_x));
       memcpy(c1_y,c2_y,sizeof(c2_y));
       c1=c2;
      }
}

void PrintData(void)
{
 freopen(_fout,"w",stdout);
 if (A[fx][fy] >= 0)
   printf("%d",A[fx][fy]);
   else printf("-1");
 fclose(stdout);
}

int main()
{
 ReadData();
 FindDToNearestDragon();
 Bellman_Ford();
 PrintData();
 
 return 0;
}