Malfunctioning Typewriter
题意
有一个
01
01
01 打字机,每次输入
0
0
0 或
1
1
1,会以
p
p
p 的概率打出正确的数字,
1
−
p
1 − p
1−p 的概率打出错误的数字。(
0.5
≤
p
<
1
0.5 \leq p < 1
0.5≤p<1)
给定
n
n
n 个长度均为
m
m
m 的
01
01
01 串,要求用打字机以任意顺序将这
n
n
n个串输出(不能有额外的错误输出),求最大成功概率。
1 ≤ n , m ≤ 1000 1 \leq n,m \leq 1000 1≤n,m≤1000
思路
首先对
n
n
n 个串建立
T
r
i
e
Trie
Trie
我们会发现:我们输入串的过程等价于在
T
r
i
e
Trie
Trie 上旅行,那么我们每一次决策会转移到下一个状态,也可能会跳出
T
r
i
e
Trie
Trie,导致输出完全错误
对于
T
r
i
e
Trie
Trie 上的一个节点
u
u
u,记它的左右孩子分别为
l
s
u
,
r
s
u
ls_u, rs_u
lsu,rsu,记
s
z
(
u
)
sz(u)
sz(u) 为
u
u
u 节点子树下的叶子个数(即有多少
01
01
01 串以该点为前缀)。
那么对于当前点
u
u
u,我们需要恰好输出
s
z
(
l
s
u
)
sz(ls_u)
sz(lsu) 个
0
0
0 和
s
z
(
r
s
u
)
sz(rs_u)
sz(rsu) 个
1
1
1
记为
f
(
s
z
(
l
s
u
)
,
s
z
(
r
s
u
)
)
f(sz(ls_u), \; sz(rs_u))
f(sz(lsu),sz(rsu))
那么我们用
f
(
x
,
y
)
f(x, y)
f(x,y) 来表示恰好输出
x
x
x 个
0
0
0,
y
y
y 个
1
1
1 的最大概率
可以发现答案就是:
∏
f
(
s
z
(
l
s
u
)
,
s
z
(
r
s
u
)
)
\prod f(sz(ls_u), sz(rs_u))
∏f(sz(lsu),sz(rsu))
f
f
f 可以用概率
D
P
DP
DP 预处理,转移:
f
x
,
y
=
max
{
p
f
x
−
1
,
y
+
(
1
−
p
)
f
x
,
y
−
1
,
p
f
x
,
y
−
1
+
(
1
−
p
)
f
x
−
1
,
y
}
.
f_{x, y} = \max \{pf_{x−1, y}+(1−p)f_{x, y−1}, \;pf_{x, y−1}+(1−p)f_{x−1, y} \}.
fx,y=max{pfx−1,y+(1−p)fx,y−1,pfx,y−1+(1−p)fx−1,y}.
意思就是在当前状态决策输出 0 0 0 还是 1 1 1,取 max \max max
#include<bits/stdc++.h>
#define fore(i,l,r) for(int i=(int)(l);i<(int)(r);++i)
#define fi first
#define se second
#define endl '\n'
#define ull unsigned long long
#define ALL(v) v.begin(), v.end()
#define Debug(x, ed) std::cerr << #x << " = " << x << ed;
const int INF=0x3f3f3f3f;
const long long INFLL=1e18;
typedef long long ll;
const int N = 1005;
const int M = 1005;
int n, m;
double p;
double f[N][N];
int cnt;
double ans = 1.0;
struct node{
int sz;
int son[2];
}tr[N * M];
void insert(std::string& s){
int now = 0;
for(auto c : s){
int ch = c - '0';
if(!tr[now].son[ch]) tr[now].son[ch] = ++cnt;
now = tr[now].son[ch];
++tr[now].sz;
}
}
void dfs(int u){
int l = (tr[u].son[0] ? tr[tr[u].son[0]].sz : 0);
int r = (tr[u].son[1] ? tr[tr[u].son[1]].sz : 0);
ans *= f[l][r];
if(tr[u].son[0]) dfs(tr[u].son[0]);
if(tr[u].son[1]) dfs(tr[u].son[1]);
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
std::cin >> n >> m >> p;
fore(i, 0, n){
std::string s;
std::cin >> s;
insert(s);
}
f[0][0] = 1;
fore(i, 1, N) f[i][0] = f[0][i] = p * f[i - 1][0];
fore(i, 1, N)
fore(j, 1, N)
f[i][j] = std::max(p * f[i - 1][j] + (1 - p) * f[i][j - 1], p * f[i][j - 1] + (1 - p) * f[i - 1][j]);
dfs(0);
std::cout << std::fixed << std::setprecision(12) << ans << endl;
return 0;
}