CF98E Help Shrek and Donkey(博弈論)
阿新 • • 發佈:2020-07-14
CF98E Help Shrek and Donkey(博弈論)
題目大意
有一副互不相同的牌共 \(n+m+1\) 張。有兩個人,第一個人 \(n\) 張,第二個人 \(m\) 張。另外有一張牌放在桌子上。
兩個人玩遊戲輪流操作(其中第一個人為先手)。有如下 \(2\) 中操作型別:
-
猜測:猜桌上的那張牌是什麼。如果猜對了則獲勝,猜錯了則失敗。操作完之後遊戲結束。
-
指定:報一張牌的名字,如果對方手上有這張牌,則將該牌丟棄,遊戲繼續;如果對方手上沒有這張牌,對方則會表示他不用由此牌。
現在假設兩個人都知道這 \(n+m+1\) 張牌分別是什麼,但是不知道桌上和對方手裡的牌具體是什麼。
若雙方都採取最優策略進行遊戲,問先手和後手獲勝概率。
若選手答案與標準答案的誤差不超過 \(10^{-9}\) 則認為正確。
資料範圍
資料範圍:\(0\le n,m\le 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\n", f[n][m], 1 - f[n][m]); return 0; }