Cod sursa(job #448496)

Utilizator nandoLicker Nandor nando Data 3 mai 2010 21:14:12
Problema Barbar Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.82 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;	
		}	
	}
	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){
			return true;	
		}else{
			do_point2(list[i][0],list[i][1],maxd);
		}
	}
	return false;
}

int cauta_rez(){
	int beg=0,end=1000000,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;	
}