• Luogu P2473 [SCOI2008]奖励关


    比较恶心的概率(期望)+状压DP,想正推2H的我瑟瑟发抖

    由于数据范围不大,因此我们可以直接状压每个宝物取或不取的情况,设(f_{i,j})表示前(i)轮且宝物是否取过的状态为(j)时的方案总数,但是我们发现这样可能会导致一些不合法的状态也得到转移,因此我们考虑倒推

    (f_{i,j})表示表示在第(1)轮到第(i-1)轮内宝物是否取过的状态为(j),第(i)轮到第(k)轮的最大期望得分,那么这样就可以通过倒推进行转移了。

    具体转移的时候我们枚举所有的宝物限制,那么转移就很明显了

    不过由于这里要求的是期望值,而每一次需要除以(n),最后的(f_{1,0})即为答案

    CODE

    #include<cstdio>
    #include<cctype>
    using namespace std;
    typedef double DB;
    const int N=16,INF=-1e9;
    int n,p[N],m,s[N],x,tot;
    DB f[105][(1<<N)+5];
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {	
    	x=0; char ch; int flag=1; while (!isdigit(ch=tc())) flag=ch^'-'?1:-1;
    	while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); x*=flag;
    }
    inline int calc(int x)
    {
    	int res=0; while (x) res+=x&1,x>>=1; return res;
    }
    inline DB max(DB a,DB b)
    {
    	return a>b?a:b;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i,j,k; read(m); read(n); tot=(1<<n)-1;
    	for (i=0;i<n;++i)
    	{
    		read(p[i]); read(x);
    		while (x) s[i]|=(1<<x-1),read(x);
    	}
    	for (i=m;i>=1;--i)
    	for (j=0;j<=tot;++j)
    	{
    		for (k=0;k<n;++k)
    		if ((s[k]&j)==s[k]) f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<k)]+p[k]); else f[i][j]+=f[i+1][j];
    		f[i][j]=(DB)f[i][j]/n;
    	}
    	return printf("%.6lf",f[1][0]),0;
    }
    
  • 相关阅读:
    HDU 1017—A Mathematical Curiosity
    N !
    L
    J
    Danganronpa
    A water problem
    hdu 5461 Largest Point
    India and China Origins hdu 5652 (BFS+二分)
    D (多校训练三) poj1919 (二分)
    Discovering Gold lightoj 1030 (dp+期望)
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9513088.html
Copyright © 2020-2023  润新知