https://community.topcoder.com/stat?c=round_overview&er=5&rd=16080
Easy
わかんないカードをS,それと対戦するカードをTとすると、勝つ回数の期待値Eは加法定理を使って、
E=Σ(T[i]がSに勝つ確率)=Σ(T[i]>S[j]となるjの数)/|S|となります。よって1つあたりの期待値は1以下です。
わかってるカードに勝てるやつがあれば期待値は1になるのでわかんないカードと対戦するよりも期待値が高くなります。よってなるべくわかってるカードに勝てるようにすればいいです。どうしても勝てないカードには弱いカードを当てます。こういう煩雑なやつはsetを使ってやると良いですね。
struct GreaterGame { vector<int> hand; vector<int> sothe; bool used[110]; double calc(vector<int> _hand, vector<int> _sothe) { hand = _hand, sothe = _sothe; int n = sz(hand); set<int> S; rep(i, 0, n) S.insert(hand[i]); vector<int> unknown; rep(i, 0, n) { hand[i]--; used[hand[i]] = true; } rep(i, 0, n) { if(sothe[i] == -1) continue; sothe[i]--; used[sothe[i]] = true; } rep(i, 0, 2 * n) { if(!used[i]) unknown.pb(i); } sort(all(sothe)); int cnt1 = 0; rer(i, n, 0) { if(sothe[i] == -1) break; int a = sothe[i]; auto b = S.upper_bound(a); //c++0x使えます。 if(b == S.end()) continue; S.erase(b); cnt1++; } if(!sz(unknown)) return cnt1; while(sz(S) > sz(unknown)) S.erase(S.begin()); int cnt2 = 0; for(int a : S) { rep(i, 0, sz(unknown)) { if(a > unknown[i]) cnt2++; } } return cnt1 + 1.0 * cnt2 / sz(unknown); } };
41 minutes 12 secs。めちゃくちゃ遅い。考察は10分くらいで終わったけど。フロー流すのは思いつかなかったけど頭すごいいいなぁ。
Medium
.#.
oooのように、#があると3つのoがあるところに#が置けなくなるので、oと#でちょうど盤面を覆い尽くした人が勝ちというゲームになります。それであり得る状態は、
#...#
#...#と
#...#
##..#と
#..##
##..#と
#...#
##.##しかないので、grundy数をdpで求めることができますが、遷移がとてもややこしいです。
盤面が負けの状態=盤面に対しどうプレイしても負ける場合
なので注意。負けの状態にできる盤面と勘違いしないように。
あとGameはGrundyを使うのを考えるのが重要で、同じ問題がn個あればGrundy数を求められることに留意しましょう。
struct PathGame { vector<string> board; int dp[1010][4]; int loop(int l, int state) { if(l == 0 && state == 0) return 0; if(l == 0 && state == 1) return 1; if(l == 0 && state == 2) return 0; if(l == 0 && state == 3) return 1; if(l == 1 && state == 0) return 1; if(l == 1 && state == 1) return 2; if(l == 1 && state == 2) return 1; if(l == 1 && state == 3) return 0; if(dp[l][state] != -1) return dp[l][state]; set<int> S; if(state == 0) { rep(i, 0, l - 2) { int a = loop(i, 1) ^ loop(l - 3 - i, 1); S.insert(a); } S.insert(loop(l - 2, 1)); } if(state == 1) { rep(i, 0, l - 2) { int a = loop(i, 3) ^ loop(l - 3 - i, 1); int b = loop(i, 2) ^ loop(l - 3 - i, 1); S.insert(a); S.insert(b); } S.insert(loop(l - 1, 1)); S.insert(loop(l - 2, 1)); S.insert(loop(l - 2, 1) ^ 1); S.insert(loop(l - 2, 3)); S.insert(loop(l - 2, 2)); } if(state == 2) { rep(i, 0, l - 2) { int a = loop(i, 3) ^ loop(l - 3 - i, 3); int b = loop(i, 2) ^ loop(l - 3 - i, 2); S.insert(a); S.insert(b); } S.insert(loop(l - 2, 3)); S.insert(loop(l - 2, 2) ^ 1); S.insert(loop(l - 1, 2)); } if(state == 3) { rep(i, 0, l - 2) { int a = loop(i, 3) ^ loop(l - 3 - i, 2); int b = loop(i, 2) ^ loop(l - 3 - i, 3); S.insert(a); S.insert(b); } S.insert(loop(l - 2, 2)); S.insert(loop(l - 2, 3) ^ 1); S.insert(loop(l - 1, 3)); } int at = 0; while(S.count(at)) at++; return dp[l][state] = at; } string judge(vector<string> _board) { board = _board; int n = 2, m = sz(board[0]); rep(i, 0, n) { rep(j, 0, m) { if(board[i][j] == '#') { rep(k, -1, 1 + 1) { if(j + k < 0 || m <= j + k) continue; if(board[1 - i][j + k] == '.') { board[1 - i][j + k] = 'o'; } } } } } memset(dp, -1, sizeof(dp)); int ans = 0; int cnt = 0, state = -1; //-1:none,0:up,1:down,2:both rep(j, 0, m) { if(state == -1) { if(board[0][j] == '.' && board[1][j] != '.') { state = 0; cnt = 0; } else if(board[0][j] != '.' && board[1][j] == '.') { state = 1; cnt = 0; } else if(board[0][j] == '.' && board[1][j] == '.') { state = 2; cnt = 1; } } else if(state == 2) { if(board[0][j] != '.' && board[1][j] != '.') { state = -1; ans ^= loop(cnt, 0); } else if(board[0][j] == '.' && board[1][j] != '.') { state = -1; ans ^= loop(cnt, 1); } else if(board[0][j] != '.' && board[1][j] == '.') { state = -1; ans ^= loop(cnt, 1); } else if(board[0][j] == '.' && board[1][j] == '.') { cnt++; } } else if(state == 0) { if(board[0][j] != '.' && board[1][j] != '.') { state = -1; ans ^= loop(cnt, 1); } else if(board[0][j] == '.' && board[1][j] != '.') { state = -1; ans ^= loop(cnt, 2); } else if(board[0][j] != '.' && board[1][j] == '.') { state = -1; ans ^= loop(cnt, 3); } else if(board[0][j] == '.' && board[1][j] == '.') { cnt++; } } else if(state == 1) { if(board[0][j] != '.' && board[1][j] != '.') { state = -1; ans ^= loop(cnt, 1); } else if(board[0][j] == '.' && board[1][j] != '.') { state = -1; ans ^= loop(cnt, 3); } else if(board[0][j] != '.' && board[1][j] == '.') { state = -1; ans ^= loop(cnt, 2); } else if(board[0][j] == '.' && board[1][j] == '.') { cnt++; } } } if(state == 0 || state == 1) { ans ^= loop(cnt, 1); } if(state == 2) { ans ^= loop(cnt, 0); } if(ans == 0) return "Sothe"; else return "Snuke"; } };
93 minutes 56 secs 2 resubmitはキツイ