解题思路
首先我们知道方差的公式是:
K
=
(
∑
i
=
1
m
(
x
i
−
p
)
2
)
/
m
K=(\sum^{m}_{i=1}(x_{i}-p)^2)/m
K=(∑i=1m(xi−p)2)/m
把
(
x
i
−
p
)
2
(x_{i}-p)^2
(xi−p)2 拆开,可以得到
K
=
(
∑
i
=
1
m
(
x
i
2
−
x
i
∗
p
−
x
i
∗
p
+
p
2
)
)
/
m
K=(\sum^{m}_{i=1}(x_{i}^2-x_{i}*p-x_{i}*p+p^2))/m
K=(∑i=1m(xi2−xi∗p−xi∗p+p2))/m也就是
K
=
(
∑
i
=
1
m
(
x
i
2
−
2
∗
x
i
∗
p
+
p
2
)
)
/
m
K=(\sum^{m}_{i=1}(x_{i}^2-2*x_{i}*p+p^2))/m
K=(∑i=1m(xi2−2∗xi∗p+p2))/m
再把 ∑拆开,就可以得到
K = ∑ i = 1 m x i 2 / m − 2 ∗ ( ∑ i = 1 m x i ) ∗ p / m + p 2 K=\sum^{m}_{i=1}x_{i}^2/m-2*(\sum^{m}_{i=1}x_{i})*p/m+p^2 K=∑i=1mxi2/m−2∗(∑i=1mxi)∗p/m+p2
令
A
=
∑
i
=
1
m
x
i
2
,
B
=
∑
i
=
1
m
x
i
A=\sum^{m}_{i=1}x_{i}^2 , B=\sum^{m}_{i=1}x_{i}
A=∑i=1mxi2,B=∑i=1mxi
又知道
p
=
∑
i
=
1
m
x
i
m
p=\frac{\sum^{m}_{i=1}x_{i}}{m}
p=m∑i=1mxi ,即
p
=
B
m
p=\frac{B}{m}
p=mB
再把这个式子带入,得
K = A / m − 2 B 2 m 2 + ( B m ) 2 K=A/m-2\frac{B^2}{m^2}+(\frac{B}{m})^2 K=A/m−2m2B2+(mB)2
再化简,得
K = A / m − 2 B 2 m 2 + B 2 m 2 K=A/m-2\frac{B^2}{m^2}+\frac{B^2}{m^2} K=A/m−2m2B2+m2B2
即 K = A / m − B 2 m 2 K=A/m-\frac{B^2}{m^2} K=A/m−m2B2
死了死了,打到手费,来吧,回到此题:
设
f
[
i
]
[
j
]
[
k
]
f[i][j][k]
f[i][j][k]表示当前走过了 i 条边,现在在 j 这个平台,经过的路程为 k的上文中A,
那么很容易可以得到状态转移方程:
f
[
i
]
[
j
]
[
k
]
=
m
i
n
(
f
[
i
]
[
j
]
[
k
]
,
f
[
i
−
1
]
[
y
]
[
k
−
w
[
y
,
j
]
]
+
w
[
y
,
j
]
2
)
f[i][j][k]=min(f[i][j][k],f[i-1][y][k-w[y,j]]+w[y,j]^2)
f[i][j][k]=min(f[i][j][k],f[i−1][y][k−w[y,j]]+w[y,j]2)
我们需要枚举y进行转移。
代码
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
const int maxn=2147483600;
int n,m,x,y,z,k,head[610],f[25][310][1020];
double ans;
struct c{
int x,next,w;
}a[610];
void add(int x,int y,int w){
a[++k].x=y;
a[k].next=head[x];
a[k].w=w;
head[x]=k;
}
int main(){
freopen("library.in","r",stdin);
freopen("library.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(y,x,z);//因为后面要枚举一个所有能走到下文中j的点,所以把每个点与能走向他的点连边
}
for(int i=0;i<20;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<=1010;k++)
f[i][j][k]=maxn;
f[0][1][0]=0;
for(int i=1;i<20;i++)
{
for(int j=2;j<=n;j++)
{
for(int k=0;k<=1010;k++)
{
for(int t=head[j];t;t=a[t].next)
{
int y=a[t].x;
if(k>=a[t].w&&f[i-1][y][k-a[t].w]<maxn)
f[i][j][k]=min(f[i][j][k],f[i-1][y][k-a[t].w]+a[t].w*a[t].w);
}
}
}
}
ans=maxn;
for(int i=1;i<20;i++)
{
for(int k=0;k<=1010;k++)
if(f[i][n][k]!=maxn)
ans=min(ans,abs(f[i][n][k]*1.0/(i*1.0)-((k*k)*1.0)/(i*1.0)/(i*1.0)));//套个方差公式
}
printf("%.4lf",ans);
}