(纪中)3528. 图书馆【DP】【数学】【方差】

119 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述


解题思路

首先我们知道方差的公式是:
K = ( ∑ i = 1 m ( x i − p ) 2 ) / m K=(\sum^{m}_{i=1}(x_{i}-p)^2)/m K=(i=1m(xip)2)/m

( x i − p ) 2 (x_{i}-p)^2 (xip)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(xi2xipxip+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(xi22xip+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/m2(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=mi=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/m2m2B2+(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/m2m2B2+m2B2

K = A / m − B 2 m 2 K=A/m-\frac{B^2}{m^2} K=A/mm2B2


死了死了,打到手费,来吧,回到此题:
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[i1][y][kw[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);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值