Cod sursa(job #1786619)

Utilizator nnnmmmcioltan alex nnnmmm Data 23 octombrie 2016 13:32:41
Problema Barbar Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.63 kb
#include<cstdio>
#include<cstring>

struct punct{int x,y;};

const int NMAX=1000,INF=NMAX*NMAX+1;
const bool DEBUG=false;

char v[NMAX+2][NMAX+2];
int d[NMAX+1][NMAX+1];
bool viz[NMAX+2][NMAX+2];

/// Sol: Creez o matrice in care tin d[i][j]= distanta minima de la (i,j) la un dragon(O(N*M)),
///      iar apoi caut binar distanta minima fata de un dragon si simulez(O(N*M*log(N))).
/// O(N*M+N*M*log(N))=O(N*M*log(N))

int linie[]=  {0,1,0,-1};
int coloana[]={1,0,-1,0};

void fill(int l,int c,int val)
{
 if(v[l][c]==0 || v[l][c]!='.' || d[l][c]<val)
    return;
 d[l][c]=val;
 for(int i=0;i<4;i++)
     fill(l+linie[i],c+coloana[i],val+1);
}

void Dragon(int l,int c,int val)
{
 for(int i=0;i<4;i++)
     fill(l+linie[i],c+coloana[i],val+1);
}

void Calculeaza_distantele(int n,int m)
{
 for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
         if(v[i][j]=='D')
            Dragon(i,j,0);
}

void fill1(int l,int c,int val)
{
 if(v[l][c]==0 || v[l][c]!='.' || d[l][c]<val || viz[l][c])
    return;
 viz[l][c]=true;
 for(int i=0;i<4;i++)
     fill1(l+linie[i],c+coloana[i],val);
}

bool Se_poate(int dist,punct in,punct sf)
{
 memset(viz,0,sizeof viz);
 for(int i=0;i<4;i++)
     fill1(in.x+linie[i],in.y+coloana[i],dist);
 for(int i=0;i<4;i++)
     if(viz[sf.x+linie[i]][sf.y+coloana[i]])
        return true;
 return false;
}

int main()
{
 FILE *in=fopen("barbar.in","r");
 int n,m;
 fscanf(in,"%d %d ",&n,&m);
 punct inc,sf;
 for(int i=1;i<=n;i++)
     {
      fscanf(in,"%s ",v[i]+1);
      for(int j=1;j<=m;j++)
          {
           if(v[i][j]=='I')
              inc.x=i,inc.y=j;
           if(v[i][j]=='O')
              sf.x=i,sf.y=j;
           d[i][j]=INF;
          }
     }
 fclose(in);

 //Bordare - Nu e nevoie matricea e deja initializata cu 0
 Calculeaza_distantele(n,m);
 FILE *out=fopen("barbar.out","w");
 if(DEBUG)
    {
     for(int i=1;i<=n;i++)
         {
          for(int j=1;j<=m;j++)
              {
               fprintf(out,"%d ",d[i][j]);
              }
          fprintf(out,"\n");
         }
    }
 int st=0,dr=n>m?n:m;
 while(st<=dr)
       {
        int mij=(st+dr)/2;
        if(Se_poate(mij,inc,sf))
           st=mij+1;
        else
           dr=mij-1;
        if(DEBUG)
           {
            fprintf(out,"%d\n",mij);
            for(int i=1;i<=n;i++)
                {
                 for(int j=1;j<=m;j++)
                     fprintf(out,"%d ",viz[i][j]);
                 fprintf(out,"\n");
                }
            fprintf(out,"\n");
           }
       }
 fprintf(out,"%d\n",dr);
 fclose(out);
 return 0;
}