Janken Master(概率dp/状压dp)

题目描述

You are supposed to play the rock-paper-scissors game. There are N players including you.

This game consists of multiple rounds. While the rounds go, the number of remaining players decreases. In each round, each remaining player will select an arbitrary shape independently. People who show rocks win if all of the other people show scissors. In this same maNer, papers win rocks, scissors win papers. There is no draw situation due to the special rule of this game: if a round is tied based on the normal rock-paper-scissors game rule, the player who has the highest programming contest rating (this is nothing to do with the round!) will be the only wiNer of the round. Thus, some players win and the other players lose on each round. The losers drop out of the game and the wiNers proceed to a new round. They repeat it until only one player becomes the wiNer.

Each player is numbered from 1 to N. Your number is 1. You know which shape the other N−1 players tend to show, that is to say, you know the probabilities each player shows rock, paper and scissors. The i-th player shows rock with ri% probability, paper with pi% probability, and scissors with si% probability. The rating of programming contest of the player numbered i is ai. There are no two players whose ratings are the same. Your task is to calculate your probability to win the game when you take an optimal strategy based on each player's tendency and rating.

输入

The input consists of a single test case formatted as follows.

N
a1
a2 r2 p2 s2
...
aN rN pN sN

The first line consists of a single integer N (2≤N≤14). The second line consists of a single integer ai (1≤ai≤N). The (i+1)-th line consists of four integers ai,ri,pi and si(1≤ai≤N,0≤ri,pi,si≤100, ri+pi+si=100) for i=2,...,N. It is guaranteed that a1,...,aN are pairwise distinct.

输出

Print the probability to win the game in one line. Your answer will be accepted if its absolute or relative error does not exceed 10−6.

样例输入

2
2
1 40 40 20

样例输出

0.8

题意

你要与 n-1 个人进行剪刀石头布的游戏。
已知 n-1 个人的出剪刀石头布的概率,与rating (胜负规则同石头剪刀布游戏, 当达成平局时,rating高的人为唯一获胜者)
对于每一轮游戏, 只有获胜的人能够晋级下一轮,当所有人都作出相同选择时,进入平局。 当场上只剩一个人时为获胜者,游戏结束。
求自己的为获胜者的最大概率。

思路

数据范围 n<=14, 显然可以用状压dp。
对于当前状态 mask, mask的二进制上为 1 时表示参与到游戏中的人。 对于每个mask, 可以通过枚举哪些人与自己出的一样, 哪些人与自己出的不一样, 同时维护一下平局时的获胜的概率。dp[mask] 则为自己出石头剪刀布三者获胜的最大概率。

代码

#include <bits/stdc++.h>
 
using namespace std;
const int maxn = 15;
const int maxm = (1 << 15);
double dp[maxm];
int n, f[maxn], x;
double r[maxn], p[maxn], s[maxn];
 
int main() {
    scanf("%d%d", &n, &x);
    --n;
    for (int i = 0; i < n; ++i) {
        int a, b, c, d;
        scanf("%d%d%d%d", &a, &b, &c, &d);
        f[i] = a / x;
        r[i] = b / 100.0;
        p[i] = c / 100.0;
        s[i] = d / 100.0;
    }
    dp[0] = 1;
    for (int mask = 1; mask < (1 << n); ++mask) {
        double rock = 0, paper = 0, scissor = 0;
        double rt = 1, pt = 1, st = 1;
        int k = 0;
        do {
            if(k==mask) continue;
            double r1 = 1, p1 = 1, s1 = 1;
            double r2 = 1, p2 = 1, s2 = 1;
            for (int i = 0; i < n; ++i) {
                if (k & (1 << i)) {
                    r1 *= r[i];
                    p1 *= p[i];
                    s1 *= s[i];
                } else if (mask & (1 << i)) {
                    r2 *= r[i];
                    p2 *= p[i];
                    s2 *= s[i];
                }
            }
            rock += r1 * s2 * dp[k];
            rt -= r1 * (p2 + s2);
            paper += p1 * r2 * dp[k];
            pt -= p1 * (r2 + s2);
            scissor += s1 * p2 * dp[k];
            st -= s1 * (r2 + p2);
        } while(k = (k-mask)&mask);
        bool fg = false;
        for (int i = 0; i < n; ++i) {
            if ((mask & (1 << i)) && f[i]) {
                fg = 1;
                break;
            }
        }
        if (!fg) {
            rock += rt, paper += pt, scissor += st;
        }
        dp[mask] = max(rock, max(paper, scissor));
    }
    printf("%.6f\n", dp[(1 << n) - 1]);
    return 0;
}
posted @ 2019-05-26 20:21  Acerkoo  阅读(171)  评论(0编辑  收藏  举报