0w1

IOI'94 The Castle ( BFS )

PEG Judge - IOI '94 - The Castle
強行枚舉每個牆壁破壞後的樣子,直接把牆壁減掉,然後檢查完再加回來就行了。雖然很明顯,但要記得意識到只有破壞牆壁的連通分量會有面積的更新,所以不需要每次都檢查全部。有一點小小卡到的是後來枚舉破壞牆壁的時候忘記要清空 vis陣列。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 50 + 5;
const int MAXM = 50 + 5;

                // W, N, E, S
const int dx[] = { 0, -1, 0, 1 };
const int dy[] = { -1, 0, 1, 0 };
const char toC[] = "WNES";

int n, m;
int cell[ MAXN ][ MAXM ];

int cnt_room, max_room;
int best_rmx, best_rmy, best_cap, best_dir;
int vis[ MAXN ][ MAXM ];
int bfs(int sx, int sy){
    int room_capacity = 0;
    queue<int> que;
    que.push( sx * MAXM + sy );
    vis[ sx ][ sy ] = 1;
    while( !que.empty() ){
        int x = que.front() / MAXM;
        int y = que.front() % MAXM;
        que.pop();
        ++room_capacity;
        for(int d = 0; d < 4; ++d){
            if( ( cell[ x ][ y ] >> d ) & 1 ) continue;
            int nx = x + dx[ d ];
            int ny = y + dy[ d ];
            assert( 1 <= nx && nx <= n && 1 <= ny && ny <= m );
            if( vis[ nx ][ ny ] ) continue;
            vis[ nx ][ ny ] = 1;
            que.push( nx * MAXM + ny );
        }
    }
    return room_capacity;
}

void solve(){
    cnt_room = max_room = 0;
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            if( !vis[ i ][ j ] ){
                ++cnt_room;
                max_room = max<int>( max_room, bfs( i, j ) );
            }
    printf("%d\n%d\n", cnt_room, max_room);

    max_room = 0;
    for(int j = 1; j <= m; ++j)
        for(int i = n; i >= 1; --i){ // west then south
            for(int d = 0; d < 4; ++d){
                if( ( cell[ i ][ j ] >> d ) & 1 ){
                    int ni = i + dx[ d ];
                    int nj = j + dy[ d ];
                    if( ni < 1 || ni > n || nj < 1 || nj > m ) continue;
                    cell[ i ][ j ] -= ( 1 << d ); // break the wall
                    
                    memset( vis, 0, sizeof(vis) );
                    int rc = bfs( i, j );
                    if( rc > max_room ){
                        max_room = rc;
                        best_rmx = i, best_rmy = j;
                        best_dir = d;
                    }

                    cell[ i ][ j ] += ( 1 << d ); // restore the wall
                }
            }
        }
    printf("%d\n", max_room);
    printf("%d %d %c\n", best_rmx, best_rmy, toC[ best_dir ]);
}

int main(){
    scanf("%d%d", &m, &n);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            scanf("%d", &cell[ i ][ j ]);
    solve();
    return 0;
}