500回記念大会。
反省点
ソース(追記:要ログイン)
http://www.topcoder.com/stat?c=problem_solution&rm=307554&rd=14429&pm=11342&cr=22919543
追記:上記リンクが要ログインなのでこちらにもソースを貼っておきます。
こちらは最小票カウンタの初期値を 100 から 1000 に変えた版です(w
他の方のソースや解説を見ると、「投票が終わるならば浮動票だけの人が1度でも最多票を獲得することはない」ということに気づくと短いコードになるみたいですね。。
実際書いてて「浮動票onlyの人が最多になるとその時点では確率M/Nだけど、固定票はその時点では確率1なので違っちゃってなんかまずいな」と思っていたのが、浮動票だけの人は結局は選ばれないということで納得です。
class MafiaGame { public: double probabilityToLose(int N, vector <int> de) { printf("%s %d\n", __FILE__, __LINE__); VI vul(N); VI vot(N); REP(i, N) vul[i]=1; vector<double> pro(N); REP(i, N) pro[i] = 1.0; int prev_n_vul = -1; int wdc = 0; do { cout<<"VUL "<<vul<<endl; int other = N-de.SZ; REP(i, N) vot[i]=0; REP(i, de.SZ) if(vul[de[i]]) { vot[de[i]]++; } else { other++; } cout<<"VOT "<<vot<<endl; cout<<"other "<<other<<endl; while(other>0) { cout<<"VO2 "<<vot<<endl; int min_vot = 1000; int min_cnt = 0; REP(i, N) if(vul[i] && vot[i]<min_vot) { min_vot=vot[i]; } REP(i, N) if(vul[i] && vot[i]==min_vot) min_cnt++; if(min_cnt<=other) { REP(i, N) if(vul[i] && vot[i]==min_vot) { vot[i]++; other--; } } else { // choose other/min_cnt double p = (double)other/min_cnt; REP(i, N) { if(other==0) break; if(vul[i] && vot[i]==min_vot) { pro[i] *= p; vot[i]++; other--; } } cout<<"PRO "<<pro<<endl; } } int n_vul = 0; int max_vot = 0; REP(i, N) if(vul[i] && max_vot < vot[i]) max_vot = vot[i]; REP(i, N) if(vul[i] && vot[i]==max_vot) n_vul++; cout<<"n_vul "<<n_vul<<endl; if(n_vul==prev_n_vul) return 0.0; prev_n_vul = n_vul; REP(i, N) vul[i] = vot[i]==max_vot ? 1 : 0; if(n_vul==1) break; if(wdc++>10) return -1.0; } while(1); double ans = 0.0; REP(i, N) if(vul[i] && ans<pro[i]) ans = pro[i]; return ans; }