Problem:
カードゲーム

問題

次のような2人で行うカードゲームがある．

このゲームでは， 1から2nまでの各整数が書かれた全部で2n枚のカードを使用する． ここで，nは1以上100以下の整数である．

このカードを2人にn枚ずつ配る．

次のルールに従って交互にカードを1枚ずつ場に出す．

場にカードが出ていないならば， 好きなカードを出すことができる．

場にカードが出ているならば， 最後に場に出たカードよりも大きい数の書かれたカードを出すことができる．

カードが出せる場合は，必ず場にカードを出す必要がある．

出せるカードが無い場合はパスとなり，相手の番になる． このとき，場に出ているカードは無くなる．

ゲームは場にカードが出ていない状態で始める．

どちらかの手持ちのカードが無くなった時点でゲームは終了する．

ゲーム終了時に相手の持っているカードの枚数を得点とする．

太郎と花子は，このゲームで対戦することになった．ゲームは太郎の番から始める． 2人は共に，出すことのできるカードのうち必ず一番小さい数が書かれたカードを出すことにしている．

太郎に配られるカードが入力されたとき，太郎と花子の得点を出力するプログラムを作成せよ．

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．

入力は n+1 行ある． 1行目には整数nが書かれている． 2行目からn+1行目までの各行には整数が1つずつ書かれており，太郎に配られるカードに書かれた整数を表す．

n が 0 のとき入力の終了を示す. データセットの数は 5 を超えない．

出力

データセットごとに 1行目には太郎の得点を， 2行目には花子の得点を出力せよ．

入出力例

入力例

5
1
7
9
6
10
10
8
7
14
18
4
11
3
17
5
19
0

出力例

3
0
2
0

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in JAVA (judge verdict: Accepted)

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) throws FileNotFoundException {

		Scanner scan = new Scanner(System.in);
		// Scanner scan = new Scanner(new File("c:\\0520-input.txt"));

		while (scan.hasNext()) {
			int n = scan.nextInt();
			if (n == 0)
				break;
			Player[] p = new Player[2];
			p[0] = new Player(n);
			p[1] = new Player(n);
			p[1].dealAll();
			for (int i = 0; i < n; i++) {
				int x = scan.nextInt();
				p[0].deal(x);
				p[1].remove(x);
			}
			game(p, 0, 0);
			System.out.println(p[1].remain());
			System.out.println(p[0].remain());
		}
		scan.close();
		System.exit(0);
	}

	private static void game(Player[] p, int tern, int card) {
		for (int i = 0; i < p.length; i++)
			if (p[i].isEmpty())
				return;
		int pay = p[tern].pay(card);
		int next = tern + 1;
		if (next == p.length)
			next = 0;
		game(p, next, pay);

	}
}

class Player {
	boolean[] card;
	int piece = 0;

	public Player(int n) {
		card = new boolean[2 * n + 1];
	}

	public int pay(int cur) {
		for (int i = cur + 1; i < card.length; i++)
			if (card[i]) {
				this.remove(i);
				return i;
			}
		return 0;
	}

	public boolean isEmpty() {
		if (piece == 0)
			return true;
		else
			return false;
	}

	public int remain() {
		/*
		 * int r = 0; for (int i = 1; i < card.length; i++) if (card[i]) r += i;
		 * return r;
		 */
		return piece;
	}

	public void remove(int x) {
		card[x] = false;
		piece--;
	}

	public void deal(int x) {
		card[x] = true;
		piece++;
	}

	public void dealAll() {
		for (int i = 1; i < card.length; i++) {
			card[i] = true;
			piece++;
		}
	}

}