洛谷 P2473 [SCOI2008]獎勵關(狀壓dp+期望)
阿新 • • 發佈:2019-03-18
== sco [1] std \n max 應該 tchar amp
題面
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; }
?
洛谷 P2473 [SCOI2008]獎勵關(狀壓dp+期望)