Yukicoder No.298 話の伝達
想定誤解法を書いてサンプルで落ちた。
solution
標本空間から$2^N$個を全列挙して生起確率を計算し、制約を満たすものの総和を取る。$O(N 2^N)$。
$O(N + M)$のDPは想定誤解法。合流が存在するので親たちの真偽が独立でないため。
標本空間からの全列挙であれば、条件付き確率ではないので独立性うんぬんとは無縁。 確率は真となる確率$p$と偽となる確率$1-p$をいい感じに使い分けて計算すればよい。
implementation
#include <cstdio>
#include <vector>
#include <tuple>
#define repeat(i,n) for (int i = 0; (i) < (n); ++(i))
using namespace std;
int main() {
int n, m; scanf("%d%d", &n, &m);
vector<vector<pair<int,double> > > g(n);
repeat (i,m) {
int a, b, c; scanf("%d%d%d", &a, &b, &c);
g[b].emplace_back(a, c/100.0);
}
double ans = 0;
repeat (s,1<<n) if ((s&(1<<0)) and (s&(1<<(n-1)))) {
double p = 1;
repeat (i,n) if (i != 0) {
double cq = 1;
for (auto it : g[i]) {
int j; double r; tie(j, r) = it;
if (s&(1<<j)) {
cq *= 1 - r;
}
}
if (s&(1<<i)) {
p *= 1 - cq;
} else {
p *= cq;
}
}
ans += p;
}
printf("%.10lf\n", ans);
return 0;
}