洛谷 P2473 [SCOI2008]奖励关(状压dp+期望)

题面

luogu

题解

\(n \leq 15\)

状压

\(f[i][S]\)表示第\(i\)轮,吃过的集合为\(S\)

正着转移好像有点复杂

考虑逆推转移(正着转移应该也行)

\(f[i][S]\)表示\([1,i-1]\)轮,吃过的集合为\(S\),第\(i\)轮到第\(k\)轮最大期望得分

Code

#include<bits/stdc++.h>

#define LL long long
#define RG register

const int N = 16;

using namespace std;
template<class T> inline void read(T &x) {
    x = 0; RG char c = getchar(); bool f = 0;
    while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
    while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
    x = f ? -x : x;
    return ;
}
template<class T> inline void write(T x) {
    if (!x) {putchar(48);return ;}
    if (x < 0) x = -x, putchar('-');
    int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
    for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}
int k, n, need[N], w[N];
double f[110][1<<N];

int main() {
    read(k), read(n);
    for (int i = 0, x; i < n; i++) {
        read(w[i]);
        while (1) {read(x); if (!x) break; x--;need[i] |= (1 << x);}
    }
    int limit = 1 << n;
    for (int i = k; i; i--)
        for (int S = 0; S < limit; S++) {
            for (int j = 0; j < n; j++)
                if ((need[j] & S) == need[j])
                    f[i][S] += max(f[i + 1][S | (1 << j)] + w[j], f[i + 1][S]);
                else f[i][S] += f[i + 1][S];
            f[i][S] /= n;
        }
    printf("%lf\n", f[1][0]);
    return 0;
}

转载于:https://www.cnblogs.com/zzy2005/p/10551495.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值