zoukankan      html  css  js  c++  java
  • [SCOI2008]奖励关

    XXXIV.[SCOI2008]奖励关

    \(n\leq 15\)就是一眼状压。但这题难点不是状压,而是期望。

    应该很容易就能想到,设\(f[i][j]\)表示前\(i\)次操作后,状态为\(j\)的期望收益。但这有个问题——我们不知道如果刷到一个负数收益应不应该选,因为我们不知道这个负数收益在后面会带给我们怎样的期望收益。

    因为必须要直到后面的内容,所以考虑倒序DP:设\(f[i][j]\)表示前\(i\)次操作后状态为\(j\),在后\(K-i\)次操作中的期望收益。这样期望就可以直接取\(\max\)了——对后面的影响已经确定。

    对于\(f[i][j]\),我们枚举一个\(k\),表示刷到第\(k\)个物品。如果\(k\)不可以选,有 f[i][j]+=f[i+1][j] ;否则,即\(k\)可以选,有f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<k)]+val[k])

    这时期望就可以正常除以\(n\)了,因为刷到所有物品的概率是均等的。

    复杂度\(O(k^22^n)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,lim,val[16],sta[16];
    double f[110][1<<16];
    int main(){
    	scanf("%d%d",&m,&n),lim=(1<<n);
    	for(int i=0,x;i<n;i++){
    		scanf("%d",&val[i]);
    		scanf("%d",&x);
    		while(x)sta[i]|=(1<<(x-1)),scanf("%d",&x);
    	}
    	for(int i=m;i;i--)for(int j=0;j<lim;j++){
    		for(int k=0;k<n;k++)if((j&sta[k])==sta[k])f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<k)]+val[k]);else f[i][j]+=f[i+1][j];
    		f[i][j]/=n;
    	}
    	printf("%lf\n",f[1][0]);
    	return 0;
    }
    

  • 相关阅读:
    Linux下php安装
    apache的安装
    线性dp
    蓝桥杯 算法训练 文章翻转
    蓝桥杯 算法训练 连通块
    Distributed Transaction Coordinator 无法启动
    WCF使用小结:(1)WCF接收HTTP POST数据的处理方法
    删除空文件夹 清除CS扩展名文件 bat
    Linux下如何修改ip地址
    is not in the sudoers file 问题解决【转载】
  • 原文地址:https://www.cnblogs.com/Troverld/p/14597154.html
Copyright © 2011-2022 走看看