[BZOJ 1076] 奖励关

Link:

BZOJ 1076 传送门

Solution:

数据范围就是题解

能比较明显看出是一道期望+状压的题目

一开始想正向推公式,结果发现每一阶段的答案并不符合后项无关性……

其实在题面中就有所提示,当前的最优解并不一定是总的最优解

这种情况下可以考虑反向$dp$来保证最优解

其中$dp[i][s]$表示当前状态为$s$,从第$i$个数到末尾的最大权值

记得每次统计完后除以$n$就好了

Code:

#include <bits/stdc++.h>

using namespace std;
double dp[105][1<<16];
int k,n,x,dat[105],st[105];

int main()
{
    scanf("%d%d",&k,&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&dat[i]);
        while(scanf("%d",&x)!=EOF&&x)
            st[i]+=(1<<x-1);
    }
    
    int MAX=(1<<n)-1;
    for(int i=k;i>=1;i--)
        for(int j=0;j<=MAX;j++)
        {
            for(int l=1;l<=n;l++)
                if((j&st[l])==st[l])
                    dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<l-1)]+dat[l]);
                else dp[i][j]+=dp[i+1][j];
            dp[i][j]/=(double)n;
        }
    printf("%.6lf",dp[1][0]);
    return 0;
}
原文地址:https://www.cnblogs.com/newera/p/9332933.html