Cod sursa(job #1786631)

Utilizator nnnmmmcioltan alex nnnmmm Data 23 octombrie 2016 13:54:11
Problema Barbar Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.14 kb
#include<cstdio>
#include<cstring>
#include<queue>

struct punct{int x,y;};

const int NMAX=1005,INF=2*NMAX;
const bool DEBUG=false;

char v[NMAX+2][NMAX+2];
int d[NMAX+1][NMAX+1];
bool viz[NMAX+2][NMAX+2];
std::queue<punct> coada;

/// 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 Calculeaza_distantele(int n,int m)
{
 while(!coada.empty())
       {
        punct sq=coada.front(),aux;
        for(int i=0;i<4;i++)
            {
             aux.x=sq.x+linie[i];
             aux.y=sq.y+coloana[i];
             if(v[aux.x][aux.y]==0 || v[aux.x][aux.y]!='.' || d[aux.x][aux.y]!=INF)
                continue;
             d[aux.x][aux.y]=d[sq.x][sq.y]+1;
             coada.push(aux);
            }
        coada.pop();
       }
}

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++)
     for(int j=1;j<=m;j++)
         d[i][j]=INF;
 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;
           if(v[i][j]=='D')
              {
               punct aux;
               for(int q=0;q<4;q++)
                   {
                    aux.x=i+linie[q],aux.y=j+coloana[q];
                    if(v[aux.x][aux.y]==0 || v[aux.x][aux.y]!='.')
                       continue;
                    d[aux.x][aux.y]=1;
                    coada.push(aux);
                   }
              }
          }
     }
 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;
}