Cod sursa(job #1896183)

Utilizator ReksioCroftOctavian Florin Staicu ReksioCroft Data 28 februarie 2017 15:31:00
Problema Barbar Scor 20
Compilator c Status done
Runda Arhiva de probleme Marime 4.78 kb
#include <stdio.h>
#include <stdlib.h>

#define nmax 1000
#define NIL -1
#define coada_size 1<<12
#define mask ( (1<<12)-1 )
#define debug 0

int v[ nmax+2 ][ nmax+2 ];
int coada[ coada_size ][2];
int poz_coada, distmax;
char *drum[nmax+2];
char dlin[4] = { -1, 0, 1, 0 };
char dcol[4] = { 0, 1, 0, -1 };
int n, m, lstart, cstart, lstop, cstop;
int *coada_drum[2];

void bordare(){
    int i;
    for( i=0; i<=n+1; i++ )
        v[i][0] = v[i][m+1] = NIL;
    for( i=0; i<=m+1; i++ )
        v[0][i] = v[n+1][i] = NIL;
}

void lee(){
    int poz_start, poz_stop, i;
    poz_start = 0;
    while( poz_start!=poz_coada ){
        poz_stop = poz_coada;
        distmax++;
        while( poz_start != poz_stop ){
            for( i=0; i<4; i++ ){
                if( v[ coada[poz_start][0] + dlin[i] ][ coada[poz_start][1] + dcol[i] ] == 0 ){///daca elementul nu a fost adaugat in coada
                    v[ coada[poz_start][0] + dlin[i] ][ coada[poz_start][1] + dcol[i] ] = distmax;
                    coada[poz_coada][0] = coada[poz_start][0] + dlin[i];
                    coada[poz_coada][1] = coada[poz_start][1] + dcol[i];
                    poz_coada = ( poz_coada + 1 ) & mask;
                }
            }
            poz_start = ( poz_start + 1 ) & mask;
        }
    }
    if( debug ){
        int j;
        for( i=0; i<=n+1; i++ ){
            for( j=0; j<=m+1; j++ ){
                printf( "%d ", v[i][j] );
            }
            printf( "\n" );
        }
        printf( "\nend of first lee\n\n" );
    }
}

void initializare(){
    int i;
    for( i=0; i<=n+1; i++ )
        drum[i] = ( char* ) calloc( m+2, sizeof(char) );
    for( i=0; i<2; i++ )
        coada_drum[i] = ( int* ) calloc( coada_size, sizeof(int) );
    for( i=0; i<=n+1; i++ )
        drum[i][0] = drum[i][m+1] = NIL;
    for( i=0; i<=m+1; i++ )
        drum[0][i] = drum[n+1][i] = NIL;
}

void deinitializare(){
    int i;
    for( i=0; i<=n+1; i++ )
        free(drum[i]);
    for( i=0; i<2; i++ )
        free( coada_drum[i] );
}

int caut_drum( int val_max ){
    initializare();
    int poz_start, poz_stop, poz_coada_drum, i, ans;
    coada_drum[0][0] = lstart;
    coada_drum[1][0] = cstart;
    drum[lstart][cstart] = 1;
    poz_start = 0;
    ans = 0;
    poz_coada_drum = 1;
    while( poz_start!=poz_coada_drum && ans==0 ){
        poz_stop = poz_coada_drum;
        while( poz_start!=poz_stop && ans==0 ){
            for( i=0; i<4; i++ ){
                if( drum[ coada_drum[0][poz_start] + dlin[i] ][ coada_drum[1][poz_start] + dcol[i] ] == 0 && v[ coada_drum[0][poz_start] + dlin[i] ][ coada_drum[1][poz_start] + dcol[i] ]>=val_max ){
                    drum[ coada_drum[0][poz_start] + dlin[i] ][ coada_drum[1][poz_start] + dcol[i] ] = 1;
                    coada_drum[0][poz_coada_drum] = coada_drum[0][poz_start] + dlin[i];
                    coada_drum[1][poz_coada_drum] = coada_drum[1][poz_start] + dcol[i];
                    if( coada_drum[0][poz_coada_drum]==lstop && coada_drum[1][poz_coada_drum]==cstop )
                        ans = 1;
                    poz_coada_drum = ( poz_coada_drum + 1 ) & mask;
                }
            }
            poz_start = ( poz_start + 1 ) & mask;
        }
    }
    if( debug ){
        int j;
        printf( "%d\n", val_max );
        for( i=0; i<=n+1; i++ ){
            for( j=0; j<=m+1; j++ ){
                printf( "%d ", drum[i][j] );
            }
            printf( "\n" );
        }
        printf( "\n\n");
    }
    deinitializare();
    return ans;
}

int cautbin( int start, int stop ){
    int pivot, ok, ans;
    ans = -1;
    while( start<stop ){
        pivot = (start + stop)/2;
        ok = caut_drum( pivot );
        if( ok==1 ){
            ans = pivot;
            start = pivot;
        }
        else
            stop = pivot - 1;
    }
    return ans;
}

int main()
{
    int i, j;
    char ch;
    FILE *fin, *fout;
    fin = fopen( "barbar.in", "r" );
    fscanf( fin, "%d%d ", &n, &m );
    for( i=1; i<=n; i++ ){
        for( j=1; j<=m; j++ ){
            ch = fgetc( fin );
            if( ch=='*' )
                v[i][j] = NIL;
            else if( ch=='D' ){///adaugam dragonul in coada
                coada[poz_coada][0] = i;
                coada[poz_coada][1] = j;
                poz_coada++;
                v[i][j] = NIL;
            }
            else if( ch=='I' ){
                lstart = i;
                cstart = j;
            }
            else if( ch=='O' ){
                lstop = i;
                cstop = j;
            }
        }
        fgetc( fin );
    }
    fclose( fin );
    bordare( n, m );
    ///alcatuim matricea cu dist minim de la un pct la un dragon
    lee();
    ///cautam binar valoarea minima pt care ajunge la rezultat
    fout = fopen( "barbar.out", "w" );
    fprintf( fout, "%d\n", cautbin( 1, distmax ) );
    fclose( fout );
    return 0;
}