hdu 3076 ssworld VS DDD(概率DP)@

来源:互联网 发布:与闺蜜类似的网络称谓 编辑:程序博客网 时间:2024/05/03 12:10

ssworld VS DDD

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2550    Accepted Submission(s): 496


Problem Description
One day, sssworld and DDD play games together, but there are some special rules in this games.
They both have their own HP. Each round they dice respectively and get the points P1 and P2 (1 <= P1, P2 <= 6). Small number who, whose HP to reduce 1, the same points will remain unchanged. If one of them becomes 0 HP, he loses. 
As a result of technical differences between the two, each person has different probability of throwing 1, 2, 3, 4, 5, 6. So we couldn’t predict who the final winner. 

 

Input
There are multiple test cases.
For each case, the first line are two integer HP1, HP2 (1 <= HP1, HP2 <= 2000), said the first player sssworld’s HP and the second player DDD’s HP. 
The next two lines each have six floating-point numbers per line. The jth number on the ith line means the the probability of the ith player gets point j. The input data ensures that the game always has an end. 
 

Output
One float with six digits after point, indicate the probability sssworld won the game.
 

Sample Input
5 51.000 0.000 0.000 0.000 0.000 0.0000.000 0.000 0.000 0.000 0.000 1.0005 50.000 0.000 0.000 0.000 0.000 1.0001.000 0.000 0.000 0.000 0.000 0.000
 

Sample Output
0.0000001.000000
 

Source
2009 Multi-University Training Contest 17 - Host by NUDT
 

Recommend

lcy


题意:
2个人分别有AB的血数,轮流扔骰子,数小的自减一血,平的不变,谁先到减0, 谁输,问A赢的概率。
题解:
dp[i][j]表示的是第一个人有i血,第二个人有j个血的时候1赢的概率。转移方程,假设p1是每一剧中第一个人赢的概率,p2是第二个人赢的概率,dp[i][j] 转化到dp[i-1][j]的概率是p2,dp[i][j]转化到dp[i][j-1]的概率是p1,那么 dp[i][j]=d[i−1][j]∗p2+dp[i][j−1]∗p1;dp[i][j]=d[i−1][j]∗p2+dp[i][j−1]∗p1;
注意事项:
因为是概率的问题,所以要考虑精度的问题,所以一般定义状态的时候就直接把dp[n][m]定义成最后的结果,不然如果最后的结果需要相加或者别的形式运算才能得到的话很有可能有精度的问题,刚开始定义dp[i][j]表示第一个人失去i格血,第二个人失去j格血的概率;
这个题一定是个脑残出的,m和n的输入是反的,而且输入并不保证输入的赢的概率和平的概率还有输的概率加起来等于1
这个题要注意要进行一次概率转化。通过概率转化排除平局的概率对答案的影响。


因为是double容易爆内存所以用滚动数组优化;


#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int N = 2008;double dp[3][N];double a[7], b[7];int main(){    int n, m;    while(scanf("%d %d", &m, &n)!=EOF)    {        memset(dp,0,sizeof(dp));        for(int i=1; i<=6; i++)            scanf("%lf",&a[i]);        for(int i=1; i<=6; i++)            scanf("%lf",&b[i]);        double p1=0, p2=0;        for(int i=1; i<=6; i++)        {            for(int j=1; j<=6; j++)            {                if(i>j)                    p1+=a[i]*b[j];                else if(i<j)                    p2+=a[i]*b[j];            }        }        dp[1][0]=dp[0][0]=1;        double sum=p1+p2;        p1=p1/sum, p2=p2/sum;        int x=0;        for(int i=1; i<=n; i++)        {            x=1^x;            for(int j=1; j<=m; j++)            {                dp[x][j]=dp[1^x][j]*p2+dp[x][j-1]*p1;            }        }        printf("%lf\n",dp[x][m]);    }    return 0;}


0 0