2021.07.16【NOIP提高B组】模拟 图书馆

2021.07.16【NOIP提高B组】模拟 图书馆

思路:

首先设f[i][j]表示第1个人走到i点,第二个人走到j点的最小方差。
根据方差化简可以看出只用维护路径和,平方和

c o d e code code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>

using namespace std;

int n, m;
int tot, head[100100];
struct node
{
	int to, next, w;
}b[1000100];
double f[30][60][1060];
double ans=1e9;

void add(int x, int y, int w)
{
	b[++tot]=(node){y, head[x], w};
	head[x]=tot;
}

int main()
{
	freopen("library.in", "r", stdin);
	freopen("library.out", "w", stdout);
	scanf("%d%d", &n, &m);
	for(int i=1; i<=m; i++)
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		add(y, x, z);
	}
	for(int i=0; i<=20; i++)
		for(int j=1; j<=n; j++)
			for(int k=0; k<=1030; k++)
				f[i][j][k]=1000000000.0;
	f[0][1][0]=0.0;	
	for(int k=0; k<=1030; k++)
		for(int i=1; i<20; i++)
			for(int j=2; j<=n; j++)
				for(int i1=head[j]; i1; i1=b[i1].next)
				{
					int v=b[i1].to;
					if(k-b[i1].w<0)
						continue;
					f[i][j][k]=min(f[i][j][k], f[i-1][v][k-b[i1].w]+b[i1].w*b[i1].w);
				}
	double ans=1000000000.0;
	for(int i=1; i<20; i++)
	{
		for(int j=0; j<=1030; j++)
		{
			if(f[i][n][j]==1000000000.0)
				continue;
			double sum=abs((f[i][n][j]*1.0/i*1.0)-(j*1.0*j)/(i*1.0*i));
			//cout<<sum<<endl;
			ans=min(ans, sum);
		}
	}
	printf("%.4lf", ans);
	return 0;
}
上一篇:最大子树和(树形dp)


下一篇:CF1528A Parsa‘s Humongous Tree