AOJ-2208: トーマス・ライトの憂鬱

keyword

Greedy Java

問題概要

N*N(N<10000)のboolean行列の、各行、各列の1の個数が与えられる。行列が一意に復元できるかどうか判定する問題。

解法

Greedyにやってみたら上手くいった。上手くいった理由は分からない。

import java.util.*;
import static java.util.Arrays.*;

public class Main {

	int[] xs, ys;

	void run(){
		Scanner in = new Scanner(System.in);
		for(;;){
			int N = in.nextInt();
			if(N == 0) return ;
			xs = new int[N];
			ys = new int[N];
			for(int i=0; i<N; i++){
				xs[i] = in.nextInt();
			}
			for(int i=0; i<N; i++){
				ys[i] = in.nextInt();
			}
			System.out.println(solve()?"Yes":"No");
		}
	}

	boolean solve(){
		int N = xs.length;
		int px = 0, qx = N-1;
		int py = 0, qy = N-1;
		int putX = 0, putY = 0;
		sort(xs);
		sort(ys);
		for(;;){
			int X = qx - px + 1, Y = qy - py + 1;
			if(X>0 && xs[px] == putY){
				px++;
			}
			else if(X>0 && xs[qx] == Y + putY){
				qx--;
				putX++;
			}
			else if(Y>0 && ys[py] == putX){
				py++;
			}
			else if(Y>0 && ys[qy] == X + putX){
				qy--;
				putY++;
			}
			else{
				return X==0 && Y==0;
			}
		}
	}

	public static void main(String args[]){
		new Main().run();
	}
}