Cod sursa(job #1023008)

Utilizator onutza999oana dragan onutza999 Data 6 noiembrie 2013 11:57:44
Problema Barbar Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.67 kb
#include <cstdio>
#include <bitset>
using namespace std;
  
#define MAXN 1005
#define INF 0x3f3f3f3f
  
int r,c,dist[MAXN][MAXN],sx,sy,fx,fy;
int list[MAXN*MAXN][3],lp=0;
bitset<MAXN> ocp[MAXN];
  
//<distante>
void do_point(int x,int y,int d){
    if(x > 0 && dist[x-1][y]!=-1 && dist[x-1][y] > d+1){
        list[lp][0]=x-1;
        list[lp][1]=y;
        list[lp][2]=d+1;
        lp++,dist[x-1][y]=d+1;
    }
    if(x < r-1 && dist[x+1][y]!=-1 && dist[x+1][y] > d+1){
        list[lp][0]=x+1;
        list[lp][1]=y;
        list[lp][2]=d+1;
        lp++,dist[x+1][y]=d+1;
    }
    if(y > 0 && dist[x][y-1]!=-1 && dist[x][y-1] > d+1){
        list[lp][0]=x;
        list[lp][1]=y-1;
        list[lp][2]=d+1;
        lp++,dist[x][y-1]=d+1;
    }
    if(y < c-1 && dist[x][y+1]!=-1 && dist[x][y+1] > d+1){
        list[lp][0]=x;
        list[lp][1]=y+1;
        list[lp][2]=d+1;
        lp++,dist[x][y+1]=d+1;
    }
}
  
void compute_dist(){
    for(int i=0;i<lp;i++){
        do_point(list[i][0],list[i][1],list[i][2]);
    }
}
//</distante>
  
//<cautare>
  
void do_point2(int x,int y,int d){
  
    if(x > 0 && !ocp[x-1][y] && dist[x-1][y]!=-1 && dist[x-1][y] >= d){
        ocp[x-1][y]=true;
        list[lp][0]=x-1;
        list[lp][1]=y;
        lp++;
    }
    if(x < r-1 && !ocp[x+1][y] && dist[x+1][y]!=-1 && dist[x+1][y] >= d){
        ocp[x+1][y]=true;
        list[lp][0]=x+1;
        list[lp][1]=y;
        lp++;
    }
    if(y > 0 && !ocp[x][y-1] && dist[x][y-1]!=-1 &&dist[x][y-1] >= d){
        ocp[x][y-1]=true;
        list[lp][0]=x;
        list[lp][1]=y-1;
        lp++;
    }
    if(y < c-1 && !ocp[x][y+1] && dist[x][y+1]!=-1 && dist[x][y+1] >= d){
        ocp[x][y+1]=true;
        list[lp][0]=x;
        list[lp][1]=y+1;
        lp++;
    }
}
  
bool check(int maxd){
    for(int i=0;i<r;i++){
        for(int j=0;j<c;j++){
            ocp[i][j]=false;
        }
    }
    if(dist[sx][sy]>=maxd){
        lp=0;
        list[lp][0]=sx;
        list[lp][1]=sy;
        lp++;
        for(int i=0;i<lp;i++){
            if(list[i][0] == fx && list[i][1] == fy && dist[fx][fy] >= maxd){
                return true;
            }else{
                do_point2(list[i][0],list[i][1],maxd);
            }
        }
    }
    return false;
}
  
int cauta_rez(){
    int beg=0,end=r*c,mdl,last,fnd=false;
    while(beg<=end){
        mdl=beg+((end-beg)>>1);
        if(check(mdl)){
            beg=mdl+1,last=mdl;fnd=true;
        }else{
            end=mdl-1;
        }
    }
    if(fnd){
        return last;
    }else{
        return -1;
    }
}
  
//</cautare>
int main(){
    FILE* fin=fopen("barbar.in","r");
    FILE* fout=fopen("barbar.out","w");
  
    fscanf(fin,"%d %d\n",&r,&c);
  
    char buf[MAXN+5];
    for(int i=0;i<r;i++){
        fgets(buf,sizeof(buf),fin);
        for(int j=0;j<c;j++){
            switch(buf[j]){
                case 'I':
                    dist[i][j]=INF;
                    sx=i,sy=j;
                    break;
                case 'O':
                    dist[i][j]=INF;
                    fx=i,fy=j;
                    break;
                case '*':
                    dist[i][j]=-1;
                    break;
                case 'D':
                    list[lp][0]=i;
                    list[lp][1]=j;
                    list[lp][2]=0;
                    lp++;
                    break;
                default:
                    dist[i][j]=INF;
                    break;
            }
        }
    }
  
    compute_dist();
    fprintf(fout,"%d ",cauta_rez());
  
    fclose(fin);
    fclose(fout);
    return 0;
}