Code Festival 上海の問題と近かったね。
http://yukicoder.me/problems/121
問題
N種類のカードからなるカードゲームがある。
初期状態で各種類のカードをA[i]枚持っている。
1枚カードを購入すると、N種類のいずれかのカードが等確率で1枚ランダムで手に入る。
各カードを3枚以上にしたい。
購入するカード枚数の期待値を答えよ。
解法
あと3枚・2枚・1枚入手しないといけないカードの種類の数をn3,n2,n1とする。
状態(n3,n2,n1)に対してDPもしくはメモ化再帰すればよい。
この類の問題で良くある「1枚カード引いても有効な(もっと必要な)カードが来ない」という場合がある。
この場合、有効なのが来るまでカードを引く期待値は、有効なカードを引く確率の逆数になる。
int N,NN[3]; int A[101]; double memo[101][101][101]; double dpdp(int n3,int n2,int n1) { if(memo[n3][n2][n1]>=0) return memo[n3][n2][n1]; memo[n3][n2][n1]=N*1.0/(n1+n2+n3); if(n1>0) memo[n3][n2][n1]+=dpdp(n3,n2,n1-1)*n1/(n1+n2+n3); if(n2>0) memo[n3][n2][n1]+=dpdp(n3,n2-1,n1+1)*n2/(n1+n2+n3); if(n3>0) memo[n3][n2][n1]+=dpdp(n3-1,n2+1,n1)*n3/(n1+n2+n3); return memo[n3][n2][n1]; } void solve() { int i,j,k,l,r,x,y; string s; cin>>N; FOR(i,N) { cin>>A[i]; if(A[i]==0) NN[2]++; if(A[i]==1) NN[1]++; if(A[i]==2) NN[0]++; } FOR(x,101) FOR(y,101) FOR(i,101) memo[x][y][i]=-1; memo[0][0][0]=0; _P("%.12lf\n",dpdp(NN[2],NN[1],NN[0])); }
まとめ
★3つなので記事作成してみました。