AOJ2024 Blackjack

問題リンク Blackjack

  • 概要

ブラックジャックの得点を計算せよ。
ブラックジャックは手持ちのカードの点数の合計が得点になる。ただし21点を超えるようなものはbustと呼び、失格となる。
カードの数字は2〜9, T, J, Q, K, Aと表す。
2〜9はそれぞれ2〜9点。T, J, Q, Kは10点。Aは得点が21点により近づくように11点もしくは1点で加算する。
手持ちのカードが2枚で21点だと、blackjackと呼び、特別な役となる。
カードの山があり、以下のルールでカードを取るかどうかを決める。
1. 得点が16以下なら、カードを1枚とる
2. 得点がちょうど17で、11点と解釈されたAがあるならばカードを1枚とる
3. これら以外の場合、終了する
手持ちのカード2枚と、現在の山の上8枚の情報が入力で与えられる。

  • 解法

実装問題です。基本的には上のルールをそのまま実装するだけです。
が、(かなり腑に落ちないんですけど)次のような決まりで得点を計算するようです。
Aが来た場合、それを11点とした場合と1点とした場合の両方を試し、結果が良かった方を採用するというのは間違いのようです。
正しくは、「Aを11点としたときに、bustすることなく終了するならばAは11点とする」です。これは、Aを1点としたときによりよい得点となろうが構わず一意に11点と決めるようです。気をつけましょう。

  • ソース
import java.util.Scanner;

//Blackjack
public class AOJ2024 {

	char[] s;
	int res;
	boolean bj;
	
	int f(char c){
		if(Character.isDigit(c))return c-'0';
		return c=='A'?1:10;
	}
	
	boolean dfs(int k, int sum, boolean ace){
		if(21<sum)return false;
		if(sum<=16||sum==17&&ace){
			int x = f(s[k]);
			if(x==1){
				if(sum+11<=21)
					if(dfs(k+1, sum+11, true))return true;
				return dfs(k+1, sum+1, ace); 
			}
			else return dfs(k+1, sum+x, ace);
		}
		else{
			if(k==2&&sum==21)bj = true;
			if(sum<=21){
				res = Math.max(res, sum);
				return true;
			}
			return false;
		}
	}
	
	void run(){
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();
		while(T--!=0){
			res = 0;
			bj = false;
			s = new char[10];
			for(int i=0;i<10;i++)s[i]=sc.next().charAt(0);
			boolean f = dfs(0, 0, false);
			System.out.println(bj?"blackjack":!f?"bust":res);
		}
	}
	
	public static void main(String[] args) {
		new AOJ2024().run();
	}
}