TopCoder SRM 578 Div1 Easy GooseInZooDivOne

問題

hxwのグリッドがある。各セルは、なにもない'.'か'v'鳥がいるかのどちらか。
鳥は二種類A, Bがいて、任意のセルの鳥について、そこからマンハッタン距離でd以下にいるセルの鳥は、全て同じ種類である。


また種類Aの鳥は一羽以上、かつ偶数羽いる。
グリッドおよびdが与えられるとき、各セルの鳥の種類の与え方は何通りあるか、
mod 1000000007で求めよ。

制約条件

h, w≦50

方針

union-findを使って、
マンハッタン距離d以内にいる鳥同士をunionでくっつける。


そしたらナップサック的なDPをしてもいいし、
奇数羽の塊がx個あるとすると、そのうち偶数個を種類Aに振り分ける場合の数は、
(2^x) / 2 = 2^x-1通りになるので、そうやって計算してもいい。

public class GooseInZooDivOne {

    char[][] map;
    int d, h, w;
    long mod = 1000000007;

	public int count(String[] field, int dist) {

        h = field.length;
        w = field[0].length();
        d = dist;
        map = new char[h][w];
        for(int i=0; i<h; i++) map[i] = field[i].toCharArray();

        int even = 0, odd = 0;
        for(int i=0; i<h; i++){
            for(int j=0; j<w; j++){
                if(map[i][j]=='v'){
                    int num = bfs(i, j);
                    if(num%2==0) even++;
                    else odd++;
                }
            }
        }
		long ans = 0;
        for(int i=0; i<even; i++){
            if(ans==0) ans = 1;
            ans = (ans * 2)%mod;
        }
        for(int i=0; i<odd-1; i++){
            if(ans==0) ans = 1;
            ans = (ans * 2)%mod;
        }
        return (int)Math.max(ans-1, 0);
	}

    int[] dx = {0, 0, 1, -1};
    int[] dy = {1, -1, 0, 0};

    int bfs(int sy, int sx){
        LinkedList<int[]> list = new LinkedList<int[]>();
        list.add(new int[]{sx, sy, 0});
        int cnt = 0;
        int[][] v = new int[h][w];

    	for(int i = 0; i < h; i++)
    		for(int j = 0; j < w; j++) v[i][j] = 1000000;
    	
    	
        while(list.size()>0){
            int[] q = list.poll();
            int x = q[0], y = q[1], dist = q[2];

            if(map[y][x]=='v'){
                map[y][x] = '.';
                cnt++; 
                dist = 0;
            }
            if(dist>=d || dist >= v[y][x]) continue;
            v[y][x] = dist;

            for(int i=0; i<4; i++){
                int nx = x + dx[i], ny = y + dy[i];
                if(nx<0 || nx>=w || ny<0 || ny>=h) continue;
                list.add(new int[]{nx, ny, dist + 1});
            }
        }

        return cnt;
    }
}