zoukankan      html  css  js  c++  java
  • CF98E Help Shrek and Donkey(博弈论)

    CF98E Help Shrek and Donkey(博弈论)

    题目大意

    有一副互不相同的牌共 (n+m+1) 张。有两个人,第一个人 (n) 张,第二个人 (m) 张。另外有一张牌放在桌子上。

    两个人玩游戏轮流操作(其中第一个人为先手)。有如下 (2) 中操作类型:

    1. 猜测:猜桌上的那张牌是什么。如果猜对了则获胜,猜错了则失败。操作完之后游戏结束。

    2. 指定:报一张牌的名字,如果对方手上有这张牌,则将该牌丢弃,游戏继续;如果对方手上没有这张牌,对方则会表示他不用由此牌。

    现在假设两个人都知道这 (n+m+1) 张牌分别是什么,但是不知道桌上和对方手里的牌具体是什么。

    若双方都采取最优策略进行游戏,问先手和后手获胜概率。

    若选手答案与标准答案的误差不超过 (10^{-9}) 则认为正确。

    数据范围

    数据范围:(0le n,mle 1000)

    解题思路

    博弈论神题

    如果你认为这只是一道简单的概率 dp,那么 E 题的称号将臭名昭著

    这题难在你猜对方,对方发现你没猜中,那么那张牌一定是桌子上的吗?显然不是,你可以故意猜自己手中的牌,诱使对方猜错

    啊这,博弈论还可以欺骗的话还怎么玩啊(主要是不好做题)

    (f[n][m]) 表示先手赢的概率,(p) 表示先手猜测的概率,列出一个表格

    相信 不信
    欺骗 (a = 1) (b = (1-f[m][n-1]))
    猜测 (c = frac m{m+1}(1-f[m-1][n])) (d = frac m{m+1}(1-f[m-1][n])+frac 1{m+1})

    那么使 (p*c+(1-p)*a=p*d+(1-p)*b) 即可

    为什么是这样,难道后手可以猜到先手的欺骗的概率,或先手猜到后手的相信的概率吗

    考虑如果后手一直选择相信或不信,那么可以看到先手的收益是两条斜率正负不同的直线,但后手总可以根据先手两条直线的斜率大小确定自己最适合的“相信概率”,而这个概率能让先手在交点处以外的点都没有在交点处更优,所以先手选交点即可

    代码

    const int N = 2005;
    int m, n;
    double f[N][N];
    int main() {
    	read(n), read(m); int mx = max(n, m);
    	for (int i = 0;i <= mx; i++) f[i][0] = 1;
    	for (int i = 1;i <= mx; i++) f[0][i] = 1.0 / (i + 1);
    	for (int i = 2;i <= n + m; i++) {
    		for (int j = 1;j < i; j++) {
    			if (i - j < 1) continue;
    			int x = j, y = i - j;
    			double inv = 1.0 / (y + 1);
    			double c = inv * y * (1 - f[y-1][x]), b = (1 - f[y][x-1]);
    			double d = c + inv;
    			double p = (1.0 - b) / (1 - c + d - b);
    			f[x][y] = p * c + (1 - p);
    		}
    	}
    	printf ("%.9lf %.9lf
    ", f[n][m], 1 - f[n][m]);
    	return 0;
    }
    
    
  • 相关阅读:
    c语言数组指针
    (4)activiti工作流引擎之uel表达式
    (3)activiti流程的挂起和激活
    (2)java程序走一遍工作流activiti
    (1)activiti认识以及数据库和插件配置
    linux 下路由配置
    lvs-dr+keepalived
    LVS-DR 配置测试
    简单认识TCP/IP协议
    mysql 主从同步-读写分离
  • 原文地址:https://www.cnblogs.com/Hs-black/p/13299508.html
Copyright © 2011-2022 走看看