AOJ 2237 The Castle
解法
bitDP.
dp[i][S][j] := i 番目(0-indexed) の敵と j 番目のねこが戦っていて,生き残っている猫が S であるときの勝てる最大確率
とする.このDPテーブルを最後の敵から最初の敵の順に(つまり後ろから)更新していく.
遷移は dp[i][S][j] = dp[i+1][S][j] * p[j][i] + max(dp[i][S & ~(1 << j)][x]) * (1 - p[j][i]) とかける.第1項は勝った場合,第2項は負けた場合である.
maxを適当に取るとTLEするので,maxを取る位置に注意すること.
また,このままDPテーブルを作るとMLEするので,直前の結果(つまり直後の敵の結果)だけを残してやる.
答えは max(dp[0][(1 << m) - 1][x]).
ソースコード
#include <bits/stdc++.h> using namespace std; double dp[2][1 << 16][16]; double memo[1 << 16]; int main() { int m, n; cin >> m >> n; vector<vector<double>> p(m, vector<double>(n)); for(int i = 0; i < m; ++i) { for(int j = 0; j < n; ++j) { cin >> p[i][j]; } } for(int S = 1; S < (1 << m); ++S) { for(int i = 0; i < m; ++i) { dp[n & 1][S][i] = 1; } } for(int i = n - 1; i >= 0; --i) { for(int S = 0; S < (1 << m); ++S) { for(int j = 0; j < m; ++j) { dp[i & 1][S][j] = 0; } for(int j = 0; j < m; ++j) { if(!((S >> j) & 1)) { continue; } dp[i & 1][S][j] = dp[(i + 1) & 1][S][j] * p[j][i] + memo[S & ~(1 << j)] * (1 - p[j][i]); } double ma = 0; for(int j = 0; j < m; ++j) { if((S >> j) & 1) { ma = max(ma, dp[i & 1][S][j]); } } memo[S] = ma; } } double res = *max_element(begin(dp[0][(1 << m) - 1]), end(dp[0][(1 << m) - 1])); cout << fixed << setprecision(10) << res << endl; }