Round D APAC Test 2017 Problem A. Vote (C++)

来源:互联网 发布:css编程放在html 编辑:程序博客网 时间:2024/06/06 00:32

Problem

A and B are the only two candidates competing in a certain election. We know from polls that exactly N voters support A, and exactly M voters support B. We also know that N is greater than M, so A will win.

Voters will show up at the polling place one at a time, in an order chosen uniformly at random from all possible (N + M)! orders. After each voter casts their vote, the polling place worker will update the results and note which candidate (if any) is winning so far. (If the votes are tied, neither candidate is considered to be winning.)

What is the probability that A stays in the lead the entire time – that is, that A will always be winning after every vote?

Input

The input starts with one line containing one integer T, which is the number of test cases. Each test case consists of one line with two integers N and M: the numbers of voters supporting A and B, respectively.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the probability that A will always be winning after every vote.

y will be considered correct if y is within an absolute or relative error of 10-6 of the correct answer. See the FAQ for an explanation of what that means, and what formats of real numbers we accept.

Limits

1 ≤ T ≤ 100.
Small dataset

0 ≤ M < N ≤ 10.
Large dataset

0 ≤ M < N ≤ 2000.

分析:

  • 这道题目类似左括号右括号排列的问题。本来想用排列组合的方法来做,结果失败了。
  • 还是用动态规划的方法来做了。因为一旦给定M,N则返回结果也定了,因而可以对较大的M,N先将所有结果算好,然后需要时直接查表返回即可。因而开了数组dp[N][N],全部初始化为0,其中dp[i][j]即为M=j,N=i时的概率。
  • 由于显然M==0时概率恒为1,所以第一列可以先确定都为1。
  • 递推式为:
    dp[i][j] = dp[i - 1][j] * (i/(i+j)) + dp[i][j - 1] * (j/(i+j));
  • 解释:

    • 当要求dp[i][j]时:假设第(i+j)个人去投票,他可能投给A, 也可能投给B,因为已知有i个人投给了A,j个人投给了B,则最后这一票有i/(i+j)的概率投给了A,有j/(i+j)的概率投给了B。
    • 当最后一票是投给A的时候,之前A一直胜的概率就为dp[i - 1][j];当最后一票是投给B的时候,之前A一直胜的概率就为dp[i][j - 1]。合起来即为dp[i][j]。
  • 最后只要直接查找相应的位置即可得到每个测试用例的结果。

代码:Github

#include <iostream>#include <cmath>#include <vector>#include <stack>#include <queue>#include <algorithm>using namespace std;typedef long long ll;errno_t err;FILE *f_input, *f_output;int T;const int N = 2001;double dp[N][N] = {0};int main() {    for (int i = 1; i < N; i++) dp[i][0] = 1;    for (int i = 1; i < N; i++) {        for (int j = 1; j < i; j++) {            double p1 = (double)i / (i + j);            double p2 = 1 - p1;            dp[i][j] = dp[i - 1][j] * p1 + dp[i][j - 1] * p2;        }    }    //open files    err = fopen_s(&f_input, "A-large-practice.in", "r");    err = fopen_s(&f_output, "out_put", "w");    //read    fscanf_s(f_input, "%d", &T);    for (int i = 1; i <= T; i++) {        int a, b;        fscanf_s(f_input, "%d %d", &a, &b);        fprintf(f_output, "Case #%d: %.8f\n", i, dp[a][b]);    }}
0 0
原创粉丝点击