sgu285:What? Where? When?(狀壓dp)

題目大意:
       又是一個遊戲。這個遊戲有兩方A,BA 方問問題,B 方答問題,每個問題都有一個答對的概率,答對了A 的積分+1 ,否則B 的積分+1 。將一個圓13 等分,逆時針編號,112 每部分上都放了一個信封,每個信封內有一個問題。第13 部分放了一個空信封,如果抽到了該部分,那麼從n 個在線問題中隨機抽一個問。圓上有一個轉盤,它的指針隨機地指向一個部分,如果該部分的信封已經用過了,那麼沿着逆時針一直轉到一個沒用過的信封。求最後比分爲6:0,6:1,6:2,6:3,6:4,6:5,5:6,4:6,3:6,2:6,1:6,0:6 的概率。

分析:
       就是一個裸的狀壓概率dpfs,i,j 表示選了的狀態爲s ,雙方積分爲i:j 的概率。

AC code:

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#define pb push_back
#define mp make_pair
#define get(x, i) (((x)>>(i-1))&1) 
typedef long long LL;
typedef double DB;
typedef long double LD;
using namespace std;

int n;
DB p[14], sum;
DB f[7][7][1<<13];
DB tp[1<<13][14];
DB ans[7][7];

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif

    cin >> n;
    for(int i = 1; i <= 12; ++i)
        cin >> p[i];
    DB x, sum = 0;
    for(int i = 1; i <= n; ++i)
        cin >> x, sum += x;
    p[13] = sum/n;
    for(int i = 0; i < (1<<13)-1; ++i)
    {
        int now = 1, s, cnt = 0;
        while(get(i, now)) now++;
        s = now, now = now%13+1;
        while(true)
        {
            cnt = 1;
            while(get(i, now)) now = now%13+1, cnt++;
            tp[i][now] = 1.0*cnt/13;
            if(now == s) break;
            now = now%13+1;
        }
    }
    f[0][0][0] = 1;
    for(int i = 0; i <= 6; ++i)
        for(int j = 0; j <= 6; ++j)
            if(i != 6 && j != 6)
                for(int s = 0; s < (1<<13); ++s)
                    if(f[i][j][s] > 0)
                        for(int l = 1; l <= 13; ++l)
                            if(!get(s, l))
                            {
                                f[i+1][j][s|(1<<(l-1))] += f[i][j][s]*tp[s][l]*p[l];
                                f[i][j+1][s|(1<<(l-1))] += f[i][j][s]*tp[s][l]*(1-p[l]);
                            }
    for(int i = 0; i <= 6; ++i)
        for(int j = 0; j <= 6; ++j)
            for(int s = 0; s < (1<<13); ++s)
                ans[i][j] += f[i][j][s];
    for(int i = 0; i <= 5; ++i)
        printf("%.3lf\n", ans[6][i]);
    for(int i = 5; i >= 0; --i)
        printf("%.3lf\n", ans[i][6]);

    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章