bzoj1076 奖励关【期望+状压dp】

解题思路:

若正着推,则一个状态会转移到两个状态,但我们不知道那一种更优,所以倒着推从两个状态转移到一个状态。

f[i][j] 表示从第i轮j这个状态开始可以得到的最高分,那么初始状态为 f[k+1][j]=0 ,我们要求的答案为 f[1][0] ,转移方程如下:

如果当前可以去第l个,则:
f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j1)]+p[j])/n;
如果不行,则:
f[i][s]+=f[i+1][s]/n

#include<bits/stdc++.h>
#define ll long long
using namespace std;  

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
    if(c=='-')f=-1,c=getchar();
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

int k,n,p[16],key[16];
double f[105][1<<15];

int main()
{
    //freopen("lx.in","r",stdin);
    k=getint(),n=getint();
    for(int i=1,j;i<=n;i++)
    {
        p[i]=getint();
        while(j=getint())
        {
            if(!j)break;
            key[i]|=(1<<j-1);
        }
    }
    for(int i=k;i;i--)
        for(int s=0;s<(1<<n);s++)
            for(int j=1;j<=n;j++)
            {
                if((key[j]&s)==key[j])
                    f[i][s]+=max(f[i+1][s],f[i+1][s|(1<<j-1)]+p[j])/n;
                else 
                    f[i][s]+=f[i+1][s]/n;
            }
    printf("%0.6f",f[1][0]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值