HDU4035:Maze
题目大意
思路
我们先考虑最朴素无华的dp,我们假设
d
p
[
i
]
dp[i]
dp[i]为从i点走出迷宫的期望步数,那么,我们可以费劲九牛二虎之力 轻松地列出dp式,如果i是叶子节点,那么
d p [ i ] = k i × d p [ 1 ] + e i × 0 + ( 1 − e i − k i ) × ( d p [ f a ] + 1 ) dp[i]=k_i\times dp[1]+e_i\times 0 + (1-e_i-k_i)\times (dp[fa]+1) dp[i]=ki×dp[1]+ei×0+(1−ei−ki)×(dp[fa]+1) ⇒ d p [ i ] = k i × d p [ 1 ] + ( 1 − e i − k i ) × ( d p [ f a ] + 1 ) \Rightarrow dp[i]=k_i\times dp[1] + (1-e_i-k_i)\times (dp[fa]+1) ⇒dp[i]=ki×dp[1]+(1−ei−ki)×(dp[fa]+1),
这句话什么意思呢?就是说它有
k
i
k_i
ki的概率被杀死回到1点,它也有
e
i
e_i
ei的可能走出迷宫,但是它是从i点走出去,所以它的贡献就是
e
i
×
0
e_i\times 0
ei×0不就是没有么?还在这里废话然后这个点还有
(
1
−
e
i
−
k
i
)
(1-e_i-k_i)
(1−ei−ki)的概率继续走下去,贡献是
(
1
−
e
i
−
k
i
)
×
(
d
p
[
f
a
]
+
1
)
(1-e_i-k_i)\times (dp[fa]+1)
(1−ei−ki)×(dp[fa]+1),所以这就是叶子结点的情况。对于不是叶子节点的情况也差不多,不过某些部分需要除以它的度数(它走到每个相邻的点的概率都是一样的),所以大概就长成这个亚子:
d p [ i ] = k i × d p [ 1 ] + ( 1 − k i − e i ) × ( d p [ f a ] + 1 ) d e g [ i ] + ∑ s o n d p [ s o n ] + 1 d e g [ i ] dp[i]=k_i\times dp[1]+\frac{(1-k_i-e_i)\times (dp[fa]+1)}{deg[i]}+\frac{\sum_{son}{dp[son]+1}}{deg[i]} dp[i]=ki×dp[1]+deg[i](1−ki−ei)×(dp[fa]+1)+deg[i]∑sondp[son]+1
⇒ \Rightarrow ⇒ d p [ i ] = k i × d p [ 1 ] + ( 1 − e i − k i ) × ( d p [ f a ] + 1 + ∑ s o n ( d p [ s o n ] + 1 ) ) d e g [ i ] dp[i]=k_i\times dp[1]+\frac{(1-e_i-k_i)\times (dp[fa]+1+\sum_{son}(dp[son]+1))}{deg[i]} dp[i]=ki×dp[1]+deg[i](1−ei−ki)×(dp[fa]+1+∑son(dp[son]+1)),
因为跟上面差不多,所以我就不详说了,但是我们会发现一个BUG,这个东西TMD 一直在来回地推,完全就是有递无归,我们难道要用高斯消元了么?不!这个TMD可能么?拜托,
1000
0
3
10000^3
100003,我们考虑一下树形动规,我们在后序遍历中,我们的
d
p
[
s
o
n
]
dp[son]
dp[son]是一个已知量,而
d
p
[
f
a
]
dp[fa]
dp[fa]和
d
p
[
1
]
dp[1]
dp[1]是未知量,所以,我们就不做了我们考虑把
d
p
[
i
]
dp[i]
dp[i]表示为另一种形式,就长成
d
p
[
i
]
=
A
[
i
]
×
d
p
[
f
a
]
+
B
[
i
]
×
d
p
[
1
]
+
C
[
i
]
dp[i]=A[i]\times dp[fa]+B[i]\times dp[1]+C[i]
dp[i]=A[i]×dp[fa]+B[i]×dp[1]+C[i],
其中
A
[
i
]
,
B
[
i
]
,
C
[
i
]
A[i],B[i],C[i]
A[i],B[i],C[i]都是我们自己要算出来的系数项。我们将
d
p
[
s
o
n
]
=
A
[
s
o
n
]
×
d
p
[
i
]
+
B
[
s
o
n
]
×
d
p
[
1
]
+
C
[
s
o
n
]
dp[son]=A[son]\times dp[i]+B[son]\times dp[1]+C[son]
dp[son]=A[son]×dp[i]+B[son]×dp[1]+C[son]带入
d
p
[
i
]
dp[i]
dp[i]的表达式中,我们设
P
[
i
]
=
1
−
e
i
−
k
i
d
e
g
[
i
]
P[i]=\frac{1-e_i-k_i}{deg[i]}
P[i]=deg[i]1−ei−ki
因为
d p [ i ] = k i × d p [ 1 ] + P [ i ] × ( d p [ f a ] + 1 ) + P [ i ] × ∑ s o n ( d p [ s o n ] + 1 ) dp[i]=k_i\times dp[1]+P[i]\times(dp[fa]+1)+P[i]\times \sum_{son}(dp[son]+1) dp[i]=ki×dp[1]+P[i]×(dp[fa]+1)+P[i]×∑son(dp[son]+1),
也就是说
d
p
[
i
]
=
k
i
×
d
p
[
1
]
+
P
[
i
]
×
(
d
p
[
f
a
]
+
1
)
+
P
[
i
]
×
∑
s
o
n
(
A
[
s
o
n
]
×
d
p
[
i
]
+
B
[
s
o
n
]
×
d
p
[
1
]
+
C
[
s
o
n
]
)
dp[i]=k_i\times dp[1]+P[i]\times (dp[fa]+1)+P[i]\times \sum_{son}(A[son]\times dp[i]+B[son]\times dp[1]+C[son])
dp[i]=ki×dp[1]+P[i]×(dp[fa]+1)+P[i]×∑son(A[son]×dp[i]+B[son]×dp[1]+C[son])
在我们合并同类项之后就长成这个亚子:
(
1
−
∑
s
o
n
A
[
s
o
n
]
×
P
[
i
]
)
×
d
p
[
i
]
=
d
p
[
f
a
]
×
P
[
i
]
+
(
∑
s
o
n
B
[
s
o
n
]
×
P
[
i
]
+
k
i
)
×
d
p
[
1
]
+
∑
s
o
n
(
C
[
s
o
n
]
+
1
)
×
P
[
i
]
+
P
[
i
]
(1-\sum_{son}A[son]\times P[i])\times dp[i]=dp[fa]\times P[i]+(\sum_{son}{B[son]\times P[i]+k_i})\times dp[1]+\sum_{son}{(C[son]+1)}\times P[i]+P[i]
(1−∑sonA[son]×P[i])×dp[i]=dp[fa]×P[i]+(∑sonB[son]×P[i]+ki)×dp[1]+∑son(C[son]+1)×P[i]+P[i]
我们看着这个东西感觉非常的不爽,那我们就设
T
[
i
]
=
1
−
∑
s
o
n
(
A
[
s
o
n
]
×
P
[
i
]
)
T[i]=1-\sum_{son}(A[son]\times P[i])
T[i]=1−∑son(A[son]×P[i]),那么根据之前
d
p
[
i
]
=
A
[
i
]
×
d
p
[
f
a
]
+
B
[
i
]
×
d
p
[
1
]
+
C
[
i
]
dp[i]=A[i]\times dp[fa]+B[i]\times dp[1]+C[i]
dp[i]=A[i]×dp[fa]+B[i]×dp[1]+C[i],所以我们两边同时除以
T
[
i
]
T[i]
T[i],就得出:
A
[
i
]
=
P
[
i
]
T
[
i
]
,
B
[
i
]
=
∑
s
o
n
(
B
[
s
o
n
]
×
P
[
i
]
+
K
[
i
]
)
T
[
i
]
,
C
[
i
]
=
∑
s
o
n
(
C
[
s
o
n
]
×
P
[
i
]
+
d
e
g
[
i
]
×
P
[
i
]
)
T
[
i
]
A[i]=\frac{P[i]}{T[i]},B[i]=\frac{\sum_{son}(B[son]\times P[i]+K[i])}{T[i]},C[i]=\frac{\sum_{son}(C[son]\times P[i]+deg[i]\times P[i])}{T[i]}
A[i]=T[i]P[i],B[i]=T[i]∑son(B[son]×P[i]+K[i]),C[i]=T[i]∑son(C[son]×P[i]+deg[i]×P[i])
所以,我们就可以跑一边树形动规就可以求出每个点的
A
[
i
]
,
B
[
i
]
,
C
[
i
]
A[i],B[i],C[i]
A[i],B[i],C[i],我们发现点1它没有爸爸(它的妈妈是被强奸了么?),那我们就可以直接算出来,点1的dp值就是
C
[
1
]
1.0
−
B
[
1
]
\frac{C[1]}{1.0-B[1]}
1.0−B[1]C[1],好,上面说了一大啪啦,但是,我们怎么判断有无解呢?实际上,我们只有除以0的时候才无解,所以在除以的时候判断一下就好了
代码理论AC
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define Int register int
#define MAXN 10005
int n;
int deg[MAXN];
double E[MAXN],K[MAXN],P[MAXN];
double A[MAXN],B[MAXN],C[MAXN];
vector <int> G[MAXN];
bool pd;
double Abs (double x){return x > 0 ? x : -x;}
void dfs (int u,int fa)
{
double tmp = 0;
double Au = P[u],Bu = K[u],Cu = 1 - K[u] - E[u];
for (Int i = 0;i < G[u].size();++ i)
{
int v = G[u][i];
if (v == fa) continue;
dfs (v,u);
if (pd) return ;
Bu += B[v] * P[u];
Cu += C[v] * P[u];
tmp += A[v] * P[u];
}
tmp = 1.0 - tmp;
if (Abs (tmp) < 1e-10)
{
pd = 1;
return ;
}
A[u] = Au / tmp,B[u] = Bu / tmp,C[u] = Cu / tmp;
}
void read (int &x)
{
x = 0;char c = getchar();int f = 1;
while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}
while (c >= '0' && c <= '9'){x = (x << 3) + (x << 1) + c - '0';c = getchar();}
x *= f;return ;
}
void write (int x)
{
if (x < 0){x = -x;putchar ('-');}
if (x > 9) write (x / 10);
putchar (x % 10 + '0');
}
signed main()
{
int times,tot = 0;
read (times);
while (times --)
{
pd = 0;
memset (G,0,sizeof (G));
memset (E,0,sizeof (E));
memset (K,0,sizeof (K));
memset (P,0,sizeof (P));
memset (A,0,sizeof (A));
memset (B,0,sizeof (B));
memset (C,0,sizeof (C));
memset (deg,0,sizeof (deg));
read (n);
for (Int i = 1;i < n;++ i)
{
int u,v;
read (u),read (v);
G[u].push_back(v);
G[v].push_back(u);
deg[u] ++,deg[v] ++;
}
for (Int i = 1;i <= n;++ i)
{
scanf ("%lf%lf",&K[i],&E[i]);
K[i] /= 100,E[i] /= 100;
}
for (Int i = 1;i <= n;++ i)
P[i] = (1 - E[i] - K[i]) * 1.0 / deg[i];
dfs (1,0);
printf ("Case %d: ",++ tot);
if (pd || Abs (1.0 - B[1]) < 1e-10) puts ("impossible");
else printf ("%.6lf\n",C[1] / (1.0 - B[1]));
}
}
/*
3
1 2
1 3
0 0
100 0
0 100
*/
//建议零的值设小一点,误差就小一点