UPC-5212: Coins I (DP)

5212: Coins I

时间限制: 1 Sec  内存限制: 128 MB
提交: 122  解决: 74
[提交] [状态] [讨论版] [命题人:admin]

题目描述

Alice and Bob are playing a simple game. They line up a row of n identical coins, all with the heads facing down onto the table and the tails upward.
For exactly m times they select any k of the coins and toss them into the air, replacing each of them either heads-up or heads-down with the same possibility. Their purpose is to gain as many coins heads-up as they can.

输入

The input has several test cases and the first line contains the integer t (1 ≤ t ≤ 1000) which is the total number of cases.
For each case, a line contains three space-separated integers n, m (1 ≤ n, m ≤ 100) and k (1 ≤ k ≤ n).

输出

For each test case, output the expected number of coins heads-up which you could have at the end under the optimal strategy, as a real number with the precision of 3 digits.

样例输入

6
2 1 1
2 3 1
5 4 3
6 2 3
6 100 1
6 100 2

样例输出

0.500
1.250
3.479
3.000
5.500
5.000
#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define rep(i,j,k) for(int i=j;i<k;i++)
#define per(i,j,k) for(int i=j;i<=k;i++)
const int maxn = 101;
typedef long long ll;

double c[maxn][maxn];    //与double组合运算必须要是双精度类型!  int/float WA
double dp[maxn][maxn]; 

void init()
{
    c[0][0]=1;
    per(i,1,100)
    {
        c[i][0]=1;
        per(j,1,i) 
            c[i][j] = c[i-1][j]+c[i-1][j-1];
    }
    /*
    p[0] = 1;
    per(i,1,100) p[i] = p[i-1]/2;
    */ 
}
int main(void)
{
    IO
    init();//组合数打表
    int T;
    cin>>T; 
    while(T--)
    {
        int n,m,k;       
        cin>>n>>m>>k;
        double pp = pow(2.0,k);  //一次(m)操作有2^k种情况
        memset(dp,0,sizeof(dp)); 
        dp[0][0] = 1;
        rep(i,0,m)
        {
            per(j,0,n)
            {
              if(dp[i][j]==0) continue;
               per(t,0,k)
               {
                  if(n-j>=k) dp[i+1][j+t] += dp[i][j]*c[k][t]/pp; 
                  else dp[i+1][j-(k-(n-j))+t] += dp[i][j]*c[k][t]/pp;  //j目前正面硬币数    
                                                                      //k-(n-j) 额外需要翻的正面硬币数  
                                                                      //j-(k-(n-j))+0 ~ j-(k-(n-j))+k j个正面的基础上得到翻k个硬币正面的机会依旧!    
               }
            }
        }
        double ans = 0.0;         
        per(i,1,n) ans += dp[m][i]*i;
		cout<<setiosflags(ios::fixed)<<setprecision(3)<<ans<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/Achanss/article/details/82252963