1. 程式人生 > >BZOJ 1076 SCOI2008獎勵關 狀壓與期望DP

BZOJ 1076 SCOI2008獎勵關 狀壓與期望DP

Problem

Problem Description

你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裡,系統將依次隨機丟擲k次寶物,每次你都可以選擇吃或者不吃(必須在丟擲下一個寶物之前做出選擇,且現在決定不吃的寶物以後也不能再吃)。

寶物一共有n種,系統每次丟擲這n種寶物的概率都相同且相互獨立。也就是說,即使前k-1次系統都丟擲寶物1(這種情況是有可能出現的,儘管概率非常小),第k次丟擲各個寶物的概率依然均為1n

獲取第 i 種寶物將得到Pi分,但並不是每種寶物都是可以隨意獲取的。第i種寶物有一個前提寶物集合Si。只有當Si中所有寶物都至少吃過一次,才能吃第i 種寶物(如果系統丟擲了一個目前不能吃的寶物,相當於白白的損失了一次機會)。注意,Pi 可以是負數,但如果它是很多高分寶物的前提,損失短期利益而吃掉這個負分寶物將獲得更大的長期利益。

假設你採取最優策略,平均情況你一共能在獎勵關得到多少分值?

Input

第一行有兩個正整數k和n,即寶物的數量和種類。以下n行分別描述一種寶物,其中第一個整數代表分值,隨後的整數依次代表該寶物的各個前提寶物(各寶物編號為1到n),以0結尾。

Output

輸出一個實數,保留六位小數,即在最優策略下平均情況的得分(即期望得分)。

Sample Input

#1

1 2
1 0
2 0

#2

6 6
12 2 3 4 5 0
15 5 0
-2 2 4 5 0
-11 2 5 0
5 0
1 2 4 5 0

Sample Output

#1

1.500000

#2

10.023470

Date Size

1<=k<=100,1<=n<=15,分值為[106,106]內的整數。

Solution

首先某些物品既然可能會有前提集合Si,而題目條件中給出了n的範圍為 1<=n<=15,那麼很容易想到,利用狀態壓縮來進行判斷是否具備前提集合,即(s&state[i])==s[i]

很容易想到利用DP來解決問題,令s表示之前已經取過寶物的狀態,即用f[i][s]表示第i輪的狀態為s時的期望得分。但是有一點問題,我們無法判斷在i輪能否能到達s的狀態,也就是有可能這個儲存的答案其實是無效的。那麼我們就可以採用倒推的方法。期望DP常用到倒推。

我們知道,E(x)=P(i)W(i)。又因為每一輪甩出某種寶物的可能性均為1n,那麼就可以先計算期望得分的總和,最後再一次除。

由此:令s依然表示之前已經取過寶物的狀態,f[i][s]表示在第i到第k輪的期望得分。那麼這個答案的儲存位置就明確了,即f[1][0]。狀態轉移方程如下:

對於具備前提集合的,則有不取和取兩種狀態:f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j1)]+c[j])

而不具備前提集合的,則只能選擇不取:f[i][s]+=f[i+1][s]

Code

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
int k,n,maxx,c[16],state[16];
double f[105][1<<15];
void input()
{
    int t;
    scanf("%d%d",&k,&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&c[i]);
        for(int j=1;;j++)
        {
            scanf("%d",&t);
            if(!t)
              break;
            state[i]|=(1<<t-1);
        }
    }
}
int main()
{
    input();
    maxx=(1<<n)-1;
    for(int i=k;i>=1;i--)
      for(int s=0;s<=maxx;s++)
      {
        for(int j=1;j<=n;j++)
        {
          if((s&state[j])==state[j])
            f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j-1)]+c[j]);
          else
            f[i][s]+=f[i+1][s];
        }
        f[i][s]/=n;
      }
    printf("%.6lf\n",f[1][0]);
    return 0;
}

相關推薦

BZOJ 1076 SCOI2008獎勵 期望DP

Problem Problem Description 你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裡,系統將依次隨機丟擲k次寶物,每次你都可以選擇吃或者不吃(必須在丟擲下一個寶物之前做出選擇,且現在決定不吃的寶物以後也不能再吃)。

[BZOJ 1076][SCOI2008]獎勵期望+Dp

方便 double spa solution bsp 所有 一個 int stream Description 你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物, 每次你都可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選

bzoj 1076: [SCOI2008]獎勵(期望DP。)

Description   你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裡,系統將依次隨機丟擲k次寶物, 每次你都可以選擇吃或者不吃(必須在丟擲下一個寶物之前做出選擇,且現在決定不吃的寶物以後也不能再吃)。  寶物一共有n種,系統每次丟擲這n種寶物的概率

BZOJ 1076: [SCOI2008]獎勵期望+DP

傳送門 題解 不能從前往後推,求期望的正確姿勢應該是從後往前。 每個物品有先決限制,我們將已獲得的物品狀壓起來。記f[i][s]為第i關開始前擁有集合s的得分期望。 列舉關卡數、集合和第i關的物品。若滿足先決條件,則f[i][s] += ma

bzoj 1076: [SCOI2008]獎勵

目前 sin 最大 ios 有一個 決定 cpp 正在 gpo Description 你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物,每次你都可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選擇,且現在決定不吃的寶物以後也不

bzoj1076: [SCOI2008]獎勵 dp

() rec ble 電子遊戲 bzoj1076 現在 得到 ios 負數 Description   你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物, 每次你都可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選擇,且現在決定

BZOJ 1076 [SCOI2008]獎勵【狀態壓縮】【期望DP

基於hzwer的部落格。 lim[i]lim[i]lim[i]表示可以獲得iii得前提。 考慮倒推,當前狀態的期望=(上一個狀態的期望+這次得到的價值)/概率 #include <bits/stdc++.h> #define db double #d

[BZOJ1076][SCOI2008]獎勵[DP+概率期望]

i+1 for += int clas digi 要求 lin sco \[f[i][j]\] 表示第1到i-1輪寶物是否取過的狀態是j,第i輪到最後一輪的最大得分。 這樣設計狀態並且倒著推,可以保證不合法的狀態是0,不會造成影響 \[nd[i]\]表示第i個物品要求的狀態

[bzoj 1076][SCOI2008]獎勵

pan 遊戲 表示 bold paper esc max efi 決定 傳送門 Description 你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物, 每次你都可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選擇,

BZOJ 1076([SCOI2008]獎勵-期望dp-從後向前)

1076: [SCOI2008]獎勵關 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 328  Solved: 199 [Submit][Status][Discuss] Description 你正在玩你最喜歡的電子遊

bzoj 1076: [SCOI2008]獎勵期望dp

1076: [SCOI2008]獎勵關 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1814  Solved: 992 [Submit][Sta

bzoj 1076: [SCOI2008]獎勵 期望dp+狀態壓縮

Description   你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裡,系統將依次隨機丟擲k次寶物, 每次你都可以選擇吃或者不吃(必須在丟擲下一個寶物之前做出選擇,且現在決定不吃的寶物以後也不能再吃)。 寶物一共有n種,系統每次丟

BZOJ 1076 [SCOI2008]獎勵

看了資料範圍一目瞭然是狀態壓縮,然而對於每種情況有選和不選兩種情況,記錄已選的狀態,每次列舉關卡時判斷是否已選。 注意這種最優選擇一般都採取倒序才能排除掉一些不可預知的不合法情況,我正序寫了仨小時不

bzoj1076 [SCOI2008]獎勵 +期望dp

題意就不說了。 分析:表示我狀壓本來就不好,加上個我不擅長的期望就徹底懵逼了。。 一開始想到把物品選或不選的方案設為狀態,設f[i][j]表示i輪後物品的狀態為j。 然後。。然後我就懵逼了。按照正常套路來說,先列舉輪(從後往前好處理),然後列舉當前狀態,然

洛谷 P2473 [SCOI2008]獎勵(dp+期望)

== sco [1] std \n max 應該 tchar amp 題面 luogu 題解 \(n \leq 15\) 狀壓 \(f[i][S]\)表示第\(i\)輪,吃過的集合為\(S\) 正著轉移好像有點復雜 考慮逆推轉移(正著轉移應該也行) \(f[i][S]\)表

1076. [SCOI2008]獎勵DP+期望

下一個 blog pos out 至少 處理 hellip 每次 選擇 Description   你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物, 每次你都可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選擇,且現在

BZOJ1076 [SCOI2008]獎勵

算法 結合 期望dp 枚舉 來源 獎勵 使用 狀態 題目 【算法】期望DP+狀壓DP 【題解】f[i][j]表示第i輪,狀態為j的期望得分。 期望DP一般倒著做,因為正著做的話會可能從很多狀態都可以滿足當前選擇,需要雙重枚舉。 而如果倒著做的話,是已知當前狀態枚舉後面的選擇

1076: [SCOI2008]獎勵

獎勵 %d col 就是 ret main sco ios pre 這題有點坑。 很容易看出是狀壓吧。 但請謹記求概率用正推,期望用逆推。 然而這題為啥我一開始覺得逆推不行呢。 就是因為前置集合。 那麽為啥不影響呢。 其實我們逆推的時候也可以判斷這個時候可不可以

[BZOJ1076]獎勵-+期望

說在前面 挺簡單的一道題。一開始看別人題解裡的dp狀態定義看的一臉mengbi… 理解狀態之後就是基礎期望了 題目 題意 (由於原題目描述十分不清真,我還是自己寫題意好啦) 現在有N個物品,K個回合。每個物品都有一個屬性:權值v。

bzoj 1076】[SCOI2008]獎勵dp+概率)

1076: [SCOI2008]獎勵關 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1817  Solved: 994 [Submit][Stat