盤面の状態は 3^9 = 19683 程度。メモ化する。
引き分けの場合は後手番の勝利に含めてしまっていい。
memo[ 盤面の状態 ] = 先手の勝率
先手は勝率を最大化し、後手は勝率を最小化する。
#include <algorithm>
#include <complex>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define REP(i, n) for(int i=0; i<(int)n; ++i)
#define FOR(i, c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(),(c).end()
#define each(i, c) FOR(i, c)
typedef long long int lli;
using namespace std;
const int BIT = 19683;
double P[2][3][3];
double memo[BIT];
int g[3][3];
bool win(int p)
{
if (g[0][0] == p && g[0][1] == p && g[0][2] == p) return true;
if (g[1][0] == p && g[1][1] == p && g[1][2] == p) return true;
if (g[2][0] == p && g[2][1] == p && g[2][2] == p) return true;
if (g[0][0] == p && g[1][0] == p && g[2][0] == p) return true;
if (g[0][1] == p && g[1][1] == p && g[2][1] == p) return true;
if (g[0][2] == p && g[1][2] == p && g[2][2] == p) return true;
if (g[0][0] == p && g[1][1] == p && g[2][2] == p) return true;
if (g[0][2] == p && g[1][1] == p && g[2][0] == p) return true;
return false;
}
bool lose(int p)
{
return win(p ^ 1);
}
int make_bit(void)
{
int bit = 0;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
bit = bit * 3 + g[i][j];
}
}
return bit;
}
const int FIRST = 0, SECOND = 1, EMPTY = 2;
double rec(int p)
{
const int bit = make_bit();
double &ret = memo[bit];
if (ret != -1) return ret;
if (win(FIRST)) return ret = 100.0;
if (lose(FIRST)) return ret = 0.0;
if (count(&g[0][0], &g[3 - 1][3], EMPTY) == 0) return ret = 0.0;
double best = (p == FIRST) ? 0 : 100.0;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (g[i][j] != EMPTY) continue;
g[i][j] = p;
double a = rec(p ^ 1) * P[p][i][j];
g[i][j] = p ^ 1;
double b = rec(p ^ 1) * (1.0 - P[p][i][j]);
best = (p == FIRST) ? max(best, a + b) : min(best, a + b);
g[i][j] = EMPTY;
}
}
return ret = best;
}
int main(int argc, char *argv[])
{
int tc;
cin >> tc;
while (tc--) {
for (int k = 0; k < 2; ++k) {
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
cin >> P[k][i][j];
P[k][i][j] /= 100.0;
}
}
}
fill(&g[0][0], &g[3 - 1][3], EMPTY);
fill(memo, memo + BIT, -1);
static int tc = 0;
printf("Case #%d: %.2lf\n", ++tc, rec(0));
}
return 0;
}