【BZOJ2318】【spoj4060】game with probability Problem 概率DP

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/46467899");
}

题解:

fi 表示剩 i 个石头、 A 先手的获胜概率。

gi 表示剩 i 个石头、 A 后手的获胜概率。

如果想选,对于 fi:

有 p 的概率进入 gi?1 ;有 1?p 的概率进入 gi

所以 fi=p?gi?1+(1?p)?gi

如果想选,对于 g(i):

有 q 的概率进入 fi?1 ;有 1?q 的概率进入 fi

所以 gi=q?fi?1+(1?q)?fi

整理得:

fi=p?gi?1+(1?p)?q?fi?11?(1?p)?(1?q)

gi=q?fi?1+(1?q)?p?gi?11?(1?p)?(1?q)

然后剩 i 个石头时A的想不想选的意愿与 fi?1、gi?1 的大小关系有关。

fi?1>gi?1 都不想选。

fi?1<gi?1 都想选。

然后对于不想选的情况,那么 p=1?p,q=1?q 就行了。

然而这样就没法用矩阵乘法了。。。

就需要黑科技,,当n很大时,其实概率已经基本不动了,,让n=min(n,1000)就好了Qwq。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1010
using namespace std;
double f[N],g[N],p,q;

int main()
{
    int i,T,n;
    for(scanf("%d",&T);T--;)
    {
        scanf("%d",&n),n=min(n,1000);
        scanf("%lf%lf",&p,&q);
        f[0]=0,g[0]=1;
        for(i=1;i<=n;i++)
        {
            if(f[i-1]>g[i-1])p=1-p,q=1-q;
            f[i]=(p*g[i-1]+(1-p)*q*f[i-1])/(1-(1-p)*(1-q));
            g[i]=(q*f[i-1]+(1-q)*p*g[i-1])/(1-(1-p)*(1-q));
            if(f[i-1]>g[i-1])p=1-p,q=1-q;
        }
        printf("%.6lf\n",f[n]);
    }
    return 0;
}
时间: 2024-09-28 16:15:04

【BZOJ2318】【spoj4060】game with probability Problem 概率DP的相关文章

BZOJ 2318: Spoj4060 game with probability Problem( 概率dp )

概率dp... http://blog.csdn.net/Vmurder/article/details/46467899 ( from : [辗转山河弋流歌 by 空灰冰魂] ) 这个讲得很好 , 推推公式就可以 O( n ) , 但是 n 最大是99999999 , 怎么破....其实 n 很大时概率基本不动了...所以只需计算到某一个较大值时就可以停下来了... ----------------------------------------------------------------

【BZOJ2318】Spoj4060 game with probability Problem 概率

[BZOJ2318]Spoj4060 game with probability Problem Description Alice和Bob在玩一个游戏.有n个石子在这里,Alice和Bob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事.取到最后一颗石子的人胜利.Alice在投掷硬币时有p的概率投掷出他想投的一面,同样,Bob有q的概率投掷出他相投的一面. 现在Alice先手投掷硬币,假设他们都想赢得游戏,问你Alice胜利的概率为多少. Input 第一行一个正整数t,

bzoj2318 Spoj4060 game with probability Problem

2318: Spoj4060 game with probability Problem Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 259  Solved: 108 [Submit][Status][Discuss] Description Alice和Bob在玩一个游戏.有n个石子在这里,Alice和Bob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事.取到最后一颗石子的人胜利.Alice在投掷硬币时有p的概率投掷出

【BZOJ 2318】 2318: Spoj4060 game with probability Problem(概率DP)

2318: Spoj4060 game with probability Problem Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 371  Solved: 173 Description Alice和Bob在玩一个游戏.有n个石子在这里,Alice和Bob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事.取到最后一颗石子的人胜利.Alice在投掷硬币时有p的概率投掷出他想投的一面,同样,Bob有q的概率投掷出他相投的一面

【bzoj2318】Spoj4060 game with probability Problem

题目描述 Alice和Bob在玩一个游戏.有n个石子在这里,Alice和Bob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事.取到最后一颗石子的人胜利.Alice在投掷硬币时有p的概率投掷出他想投的一面,同样,Bob有q的概率投掷出他相投的一面. 现在Alice先手投掷硬币,假设他们都想赢得游戏,问你Alice胜利的概率为多少. 输入 第一行一个正整数t,表示数据组数. 对于每组数据,一行三个数n,p,q. 输出 对于每组数据输出一行一个实数,表示Alice胜利的概率,保

rockethon2015 G2题 Inversions problem 概率dp

题意:给定n,k.k次操作,每次等概率将一个区间翻转,问最后逆序数对的期望. 思路:设dp[i][j]表示a[i]在a[j]前面的概率.每次枚举翻转的区间,更新dp[i][j],复杂度为O(n^4×k).详见代码: /********************************************************* file name: G.cpp author : kereo create time: 2015年02月09日 星期一 11时32分13秒 ************

Codeforces 513G1 513G2 Inversions problem 概率dp

题目链接:点击打开链接 题意: 给定n ,k 下面n个数表示有一个n的排列, 每次操作等概率翻转一个区间,操作k次. 问: k次操作后逆序数对个数的期望. 思路: dp[i][j]表示 a[i] 在a[j] j前面的概率 初始就是 dp[i][j]  = 1( i < j ) 则对于翻转区间 [i, j], 出现的概率 P = 1 / ( n * (n+1) /2) 并且会导致 [i, j]内元素位置交换,枚举这次翻转的区间时所有的转移情况 #include <stdio.h> #inc

[CF442B] Andrey and Problem (概率dp)

题目链接:http://codeforces.com/problemset/problem/442/B 题目大意:有n个人,第i个人出一道题的概率是pi,现在选出一个子集,使得这些人恰好出一个题的概率最大.问最大概率. 可以仿照背包问题来做,即每个人可问可不问. f[i][j]代表从前i个人里问j个人所获得1个题的最大概率. f[i][j] = max{ f[i-1][j], f[i-1][j-1]*(1-p[i])+z[i-1][j-1]*p[i] }; z[i][j]为从前i个人里问j个人所

Problem A CodeForces 148D 概率dp

题意:袋子里有w只白鼠和b只黑鼠.龙和公主轮流从袋子里抓老鼠.谁先抓到白色老师谁就赢.公主每次抓一只老鼠,龙每次抓完一只老鼠之后会有一只老鼠跑出来.每次抓老鼠和跑出来的老鼠都是随机的.如果两个人都没有抓到白色老鼠则龙赢.公主先抓.问公主赢的概率. 做了这么多概率dp的题目了,本来接的差不多了,结果一做还是不会...... 下面是看了别人的思路 win[i][j] = i * 1.0 / (i + j); //i只白老鼠j只黑老鼠时公主选白老鼠 win[i][j] += lost[i][j-1]