传送门

题意:$n$种宝物,出现$k$次每次一种,每种宝物有价值和吃掉它之前必须要吃掉的宝物的集合,求采取最优策略的期望最大价值

1<=k<=100,1<=n<=15,分值为[-10^6,10^6]内的整数。


 

看到$n$应该想到状压....

$f[i][s]$表示前$i$次已经吃掉的集合为$s$的期望最大值

然而正推的话,答案是谁呢?

所以倒推,表示这个状态到结束得到的期望最大值

转移枚举出现的宝物,最后乘上概率$\frac{1}{n}$

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=105,S=1<<15;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int m,n,val[N],need[N];
double f[N][S];
int main(){
    freopen("in","r",stdin);
    m=read();n=read();
    for(int i=0;i<n;i++){
        val[i]=read();int x=read();
        while(x) need[i]|=(1<<(x-1)),x=read();
    }
    int All=1<<n;
    for(int i=m;i>=1;i--)
        for(int s=0;s<All;s++){
            for(int j=0;j<n;j++){
                if((s&need[j])==need[j]) f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j)]+val[j]); 
                else f[i][s]+=f[i+1][s];
            }
            f[i][s]/=n;
        }
    printf("%.6lf",f[1][0]);
}

 

相关文章:

  • 2021-06-24
  • 2021-12-28
  • 2021-08-04
  • 2021-07-29
  • 2022-12-23
  • 2021-12-01
  • 2022-01-30
  • 2021-07-27
猜你喜欢
  • 2022-12-23
  • 2021-10-05
  • 2021-10-01
  • 2021-11-28
  • 2021-11-04
  • 2021-10-17
  • 2021-09-24
相关资源
相似解决方案