DOJ_#8解題報告

T1

原題可以轉化爲:
給出一個圖 (N10000,M100000) ,給每個點染色(共兩種顏色),使任意一條邊的兩個端點顏色不同,不能則輸出“Impossible”。

分析
對每個點搜索,此時染色爲X,則相鄰點染色爲X xor 1 。對於每個聯通塊,都要取較少的一個染色數量,即( min(cnt[0],cnt[1]) )。DFS函數返回能否進行染色,對於一個聯通塊,第一個點染什麼顏色都是可以的(兩顏色等價),但是最後ans要加上少的那個顏色。

上代碼

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std ;

const int N = 1e4 + 5 ;

int n, m, ans ;
int cnt[ 2 ], inq[ N ] ; // 染色情況
vector < int > edge[ N ] ;

void init() {
    memset( inq , 0xff , sizeof( inq ) ) ;
    scanf( "%d %d", &n, &m ) ;
    for ( int i = 1 ; i <= m ; i ++ ) {
        int a, b ; scanf( "%d %d", &a, &b ) ;
        edge[ a ].push_back( b ) ;
        edge[ b ].push_back( a ) ;
    }
}

// dfs染色,一個顏色的相對顏色爲這個顏色 xor 1
bool dfs( int a , int b ) {
    inq[ a ] = b ; cnt[ b ] ++ ;
    for ( int i = 0 ; i < edge[ a ].size() ; i ++ ) {
        int node = edge[ a ][ i ] ;
        if ( inq[ node ] == -1 )
            if ( !dfs( node , b ^ 1 ) )
                return false ;
            else
                continue ;
        else
            if ( inq[ node  ] == b )
                return false ;
            else
                continue ;
    }
    return true ;
}
bool figure() {
    for ( int i = 1 ; i <= n ; i ++ )
        if ( inq[ i ] == -1 && edge[ i ].size() ) { // 是否可進行染色
            cnt[ 0 ] = cnt[ 1 ] = 0 ;
            if ( !dfs( i , 1 ) ) return false ;
            else    ans += min( cnt[ 0 ] , cnt[ 1 ] ) ;
        }
    return true ;
}
int main() {
    init() ;
    if ( figure() )
        printf( "%d\n", ans ) ;
    else
        printf( "Impossible\n" ) ;
    return 0 ;
}

T2

一個表(N,M1000 ) ,每組方形的‘#’表示一支船,但是船不能相碰。

分析
對於每一個點,沒有標記過,就搜索,擴張(先橫向擴張,再縱向擴張),並標記新點。擴張的時候注意返回“Bad placement”的情況。(本來覺得應該會T)

上代碼(這道題寫得挫,勿怪)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

const int N = 1e3 + 5 ;

int n, m, cnt ;
int plat[ N ][ N ] ;

void init() {
    char ss[ N ] ;
    scanf( "%d %d", &n, &m ) ;
    for ( int i = 1 ; i <= n ; i ++ ) {
        scanf( "%s", ss + 1 ) ;
        for ( int j = 1 ; j <= m ; j ++ )
            if ( ss[ j ] == '.' )
                plat[ i ][ j ] = -1 ;
            else
                plat[ i ][ j ] = 0 ;
    }
}

bool go_row( int &a , int &b , int c ) {
    while ( a > 1 && !plat[ a - 1 ][ c ] )  a -- ;
    while ( b < n && !plat[ b + 1 ][ c ] )  b ++ ;
    if ( plat[ a - 1 ][ c ] != -1 && a > 1 )    return false ;
    if ( plat[ b + 1 ][ c ] != -1 && b < n )    return false ;
    return true ;
}
int judge( int a , int b , int c ) {
    if ( c <= 0 )   return 0 ;
    if ( c > m )   return 0 ;
    int flag = 0 ;
    for ( int i = a ; i <= b ; i ++ )
        switch ( plat[ i ][ c ] ) {
            case -1 :
                if ( !flag )    flag = 1 ;
                break ;
            case 0 :
                continue ;
            default :
                return -1 ;
        }
    if ( flag )    return  0 ;
    else    return 1 ;
}
bool go_col( int a , int b , int &c , int &d ) {
    int temp = 0 ;
    while ( temp = judge( a , b , c - 1 ), temp == 1 )  c -- ;
    if ( temp == -1 )   return false ;
    while ( temp = judge( a , b , d + 1 ), temp == 1 )  d ++ ;
    if ( temp == -1 )   return false ;
    return true ;
}
bool search( int a , int b , int c , int d ) {
    if ( !go_row( a , b , c ) ) return false ;
    if ( !go_col( a , b , c , d ) ) return false ;
    cnt ++ ;
    for ( int i = a ; i <= b ; i ++ )
        for ( int j = c ; j <= d ; j ++ )
            plat[ i ][ j ] = cnt ;
    return true ;
}
bool figure() {
    for ( int i = 1 ; i <= n ; i ++ )
        for ( int j = 1 ; j <= m ; j ++ )
            if ( !plat[ i ][ j ] )
                if ( !search( i , i , j , j ) )
                    return false ;
    return true ;
}
int main() {
    init() ;
    if ( figure() )
        printf( "There are %d ships.\n", cnt ) ;
    else
        printf( "Bad placement.\n" ) ;
    return 0 ;
}

T3

多個點,向上下左右擴張,問到目標點,需要多少步,裸BFS,多個點都入隊就好了。

分析
一開始多個點入隊,dist = 0, book = true,BFS到所有點就好了。

上代碼

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std ;

const int N = 500 + 2 ;
const int DIR[ 4 ][ 2 ] = { { -1 , 0 } , { 1 , 0 } ,
                            { 0 , -1 } , { 0 , 1 } } ;

int n, m, c1, c2 ;

#define Dist( a ) dist[ a.x ][ a.y ]
#define Book( a ) book[ a.x ][ a.y ]
int dist[ N ][ N ] ;
bool book[ N ][ N ] ;
struct node {
    int x, y ;
    inline node move( int to ) {
        node a = (node){ x + DIR[ to ][ 0 ] , y + DIR[ to ][ 1 ] } ;
        return a ;
    }
} ;
queue < node > Q ;
inline bool judge( node a ) {
    if ( a.x >= 1 && a.x <= n )
        if ( a.y >= 1 && a.y <= m )
            return true ;
    return false ;
}
void bfs() {
    while ( !Q.empty() ) {
        node temp = Q.front() ; Q.pop() ;
        for ( int i = 0 ; i < 4 ; i ++ ) {
            node nown = temp.move( i ) ;
            if ( judge( nown ) && !Book( nown ) ) {
                Dist( nown ) = Dist( temp ) + 1 ;
                Book( nown ) = true ; Q.push( nown ) ;
            }
        }
    }
}
int main() {
    scanf( "%d %d %d %d", &n, &m, &c1, &c2 ) ;
    for ( int i = 1 ; i <= c1 ; i ++ ) {
        int a, b ; scanf( "%d %d", &a, &b ) ;
        Q.push( (node){ a , b } ) ;
        dist[ a ][ b ] = 0 ; book[ a ][ b ] = true ;
    }   bfs() ;
    for ( int i = 1 ; i <= c2 ; i ++ ) {
        int a, b ; scanf( "%d %d", &a, &b ) ;
        printf( "%d\n", dist[ a ][ b ] ) ;
    }
    return 0 ;
}

以上

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章