Cows and Cars - 概率dp 对题目发出质疑

Cows and Cars
Input:
 standard input
Output: standard output
Time Limit: 4 seconds

In television contests, participants are often asked to choose one from a set of or doors for example, one or several of which lead to different prizes. In this problem we will deal with a specific kind of such a contest. Suppose you are given the following challenge by the contest presenter:


In front of you there are three doors. Two of them hide a cow, the other one hides your prize - a car.
After you choose a door, but before you open it, I will give you an hint, by opening one of the doors which hides a cow (I'll never open the door you have chosen, even if it hides a cow). You will then be able to choose if you want to keep your choice, or if you wish to change to the other unopened door. You will win whatever is behind the door you open.

In this example, the probability you have of winning the car is 2/3 (as hard as it is to believe), assuming you always switch your choice when the presenter gives you the opportunity to do so (after he shows you a door with a cow). The reason of this number (2/3) is this - if you had chosen one of the two cows, you would surely switch to the car, since the presenter had shown you the other cow. If you had chosen the car, you would switch to the remaining cow, therefore losing the prize. Thus, in two out of three cases you would switch to the car. The probability to win if you had chosen to stick with your initial choice would obviously be only 1/3, but that isn't important for this problem.


In this problem, you are to calculate the probability you have of winning the car, for a generalization of the problem above:

- The number of cows is variable

- The number of cars is variable (number of cows + number of cars = total number of doors)

- The number of doors hiding cows that the presenter opens for you is variable (several doors may still be open when you are given the opportunity to change your choice)



You should assume that you always decide to switch your choice to any other of the unopen doors after the presenter shows you some doors with cows behind it.

 

Input

There are several test cases for your program to process. Each test case consists of three integers on a line, separated by whitespace. Each line has the following format:

NCOWS NCARS NSHOW

Where NCOWS is the number of doors with cows, NCARS is the number of doors with cars and NSHOW is the number of doors the presenter opens for you before you choose to switch to another unopen door.

The limits for your program are:

1 <= NCOWS <= 10000

1 <= NCARS <= 10000

0 <= NSHOW < NCOWS

 

Output

For each of the test cases, you are to output a line containing just one value - the probability of winning the car assuming you switch to another unopen door, displayed to 5 decimal places.

  

Sample input

2 1 1
5 3 2
2000 2700 900

 

Sample output

0.66667
0.52500

0.71056


题意:有n头牛,m辆车,有k次展现一头牛的机会,每次展示后,你都会去选择其他的门,问你最后能拿到车的概率。

思路:

首先借鉴一下其他人的思路:

P(赢得汽车)

=P(最开始选的那扇门后是山羊)*P(在最开始选的那扇门后是山羊的情况下剩下那扇门后是车)+P(最开始选的那扇门后是车)*P(在最开始选的那扇门后是车的情况下剩下那扇门后是车)

=2/3*1+1/3*0=2/3

用专业术语来说,设A={最开始选的那扇门后是山羊},B={第二次选的门后是车}

则由全概率公式得:

UVa 10491 Cows and Cars (概率&amp;广义三门问题 )

那么对于此题,同样可以用上面的公式计算得出:

UVa 10491 Cows and Cars (概率&amp;广义三门问题 )

这个代码确实是和样例一样的,但是存在一个问题,就是你的P(A)是你第一次选择的是车的概率,然而,经过k次的变化之后,你当前选择的不一定还是车,问题就在这里。这样做的话题意就理解为你选择之后,同时展示k头牛,你再选择一个其余的问的概率。

但是从题目:several doors may still be open when you are given the opportunity to change your choice

   以及you always decide to switch your choice可以看出不是这个题意



我的思路:用dp来做,dp[i][0]表示当前还有i次展现牛的机会,并且当前选择的是牛,dp[i][1]同理,并且当前选择的是车。我们先考虑dp[i][0]的转移,当前情况下,共有p=n-k+i的牛,有m辆车,而且你当前选择的是牛,因为展现出来一头牛了,那么你有(p-2)/(p+m-2)的可能性选一头牛,有m/(p+m-2)的可能性选一辆车。

那么dp[i][0]=dp[i-1][0]*(p-2)/(p+m-2)+dp[i-1][1]*m/(p+m-2);

同理dp[i][1]=dp[i-1][0]*(p-1)/(p+m-2)+dp[i-1][1]*(m-1)/(p+m-2);

最后结果和答案不同,但是差距也不是很大。不管我的想法对不对,做了这么多的题目,敢于质疑就是一个突破。而且按照我的思路去写上面那个题意,答案也能跟样例对的上。

我的代码如下:

#include<cstdio>
#include<cstring>
using namespace std;
int n,m,k;
double dp[10010][2],ans;
int main()
{
    int i,j,p,q;
    dp[0][0]=0;
    dp[0][1]=1;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        for(i=1;i<=k;i++)
        {
            p=n-k+i;
            q=p+m-2;
            dp[i][0]=dp[i-1][0]*(p-2)/q+dp[i-1][1]*m/q;
            dp[i][1]=dp[i-1][0]*(p-1)/q+dp[i-1][1]*(m-1)/q;
        }
        ans=(n*dp[k][0]+m*dp[k][1])/(n+m);
        printf("%.5f\n",ans);
    }
}

网上题意的代码如下:

#include<cstdio>
#include<cstring>
using namespace std;
int n,m,k;
double dp[10010][2],ans;
int main()
{
    int i,j,p,q;
    dp[0][0]=0;
    dp[0][1]=1;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        ans=1.0*(n+m-1)*m/(n+m)/(n+m-1-k); //网上代码

        dp[1][0]=1.0*(m)/(n+m-k-1);    //按照样例题意的我的思路
        dp[1][1]=1.0*(m-1)/(n+m-k-1);
        ans=(n*dp[1][0]+m*dp[1][1])/(n+m);
        printf("%.5f\n",ans);
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值