• codevs4438 YJQ Runs Upstairs


    Description

    学校科技楼一共有 (N) 层,而神犇YJQ每天都在科技楼 (N) 楼的机房写代码。这天,他准备从科技楼 (1) 楼爬到 (N) 楼。有个 (M) 连接不同楼层的楼梯,爬每个楼梯需要一定的体力值。楼梯一定是从低处通往高处的。(但是由于楼房的设计比较奇怪,第 (i) 楼并不一定在第 (i−1) 楼上面,也就是说给出的边不保证 (x<y) ,但保证图为DAG,请自行处理楼层之间的高度关系)。为了省时间,YJQ一定只会上楼梯而不会下楼梯,即楼梯间不会形成环路。而且出于人性化考虑,不管YJQ选择什么路线上楼,他爬的楼梯数量一定小于 (20) 。为了使体力消耗尽量平稳,YJQ需要选择一条“每个楼梯消耗体力值的方差最小”的路径上楼。请帮助YJQ计算出这个最小方差。

    Input Description

    第一行包含 (2) 个整数 (N,M) 表示科技楼楼层数和楼梯数; 接下来 (M) 行,每行 (3) 个数, (x,y,z) 表示存在一条由 (x) 层通往平台 (y) 层的楼梯,爬这个楼梯需要消耗 (z) 的体力值。

    Output Description

    一行 (1) 个实数,表示最小方差,精确到小数点后 (4) 位。

    Sample Input

    4 4 1 2 1 2 4 3 1 3 2 3 4 3

    Sample Output

    0.2500

    Data Size & Hint

    对于 (30\%) 的数据,(N≤10,M≤20);

    另有 (20\%) 的数据 (N≤35,M≤220,Zin[0,1]);

    对于 (100\%) 的数据 (2≤N≤50,M≤300,0≤Z≤50) 保证至少存在一条由 (1)(N) 的路径。

    Solution

    方差 (s^2) 满足 $$ s^2 = frac{1}{n} imessumn_{i=1}(x_i-overline{x})2 = frac{1}{n} imes (sumn_{i=1}x_i2-2overline{x}(sum^n_{i=1}x_i) + noverline{x}^2)$$

    那么在 (sum xi) 一定时,(sum x_i^2) 最小时方差最小。
    于是 (f[i][j][k]) 表示走到 (i) 号点,走了 (j) 个楼梯,(sum x_i)(k) 时,最小的平方和。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define rep(i, a, b) for (int i = a; i <= b; i++)
    #define drp(i, a, b) for (int i = a; i >= b; i--)
    
    inline int read() {
    	int x = 0, flag = 1; char ch = getchar(); while  (!isdigit(ch)) { if (ch == '-') flag = -1; ch = getchar(); }
    	while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
    }
    
    inline void write(int x) {
    	if (!x) { putchar('0'); return; } if (x < 0) putchar('-'), x = -x;
    	char buf[20] = ""; int top = 0; while (x) buf[++top] = x % 10 + '0', x /= 10; while (top) putchar(buf[top--]);
    }
    
    struct edge { int v, w, next; }e[501]; int tot;
    int n, g[501];
    int dp[51][21][16001], INF = 1000000007;
    int deg[51], sum;
    int q[5000], r, l = 1;
    
    inline void add(int u, int v, int w) { e[++tot] = edge{ v, w, g[u] }; g[u] = tot; deg[v]++; sum += w; }
    
    #define Min(a, b) a = min(a, b)
    void topu() {
    	rep(i, 1, n) if(!deg[i]) q[++r] = i;
    	dp[1][0][0] = 0;
    	while(l <= r) {
    		int u = q[l++];
    		rep(j, 0, 19) rep(k, 0, sum) if(dp[u][j][k] ^ INF) for(int i = g[u]; i; i = e[i].next) {
    			int v = e[i].v, w = e[i].w;
    			if(k + w <= sum) Min(dp[v][j + 1][k + w], dp[u][j][k] + w * w);
    		}
    		for(int i = g[u]; i; i = e[i].next) if(!--deg[e[i].v]) q[++r] = e[i].v;
    	}
    }
    
    int main() {
    	n = read(); int m = read();
    	while(m--) { int u = read(), v = read(); add(u, v, read()); }
    	memset(dp, 127, sizeof dp); INF = dp[0][0][0];
    	topu();
    	double ans = 1e9;
    	rep(j, 1, 20) rep(k, 0, sum) Min(ans,(dp[n][j][k] * 1.0 / j) - (k * 1.0 * k) / (j * 1.0 * j));
    	printf("%.4lf", ans);
    	return 0;
    }
    
  • 相关阅读:
    sql笔记
    虚函数和抽象类笔记
    构造函数和静态构造函数 笔记
    在与sql server 建立连接时出现与网络相关的或特定于实例的错误
    类型转换 笔记
    test
    document.body和document.documentElement比较
    sql2005 存储过程实现分页
    新闻发布用到的存储过程和触发器
    SQL数据查询实例1
  • 原文地址:https://www.cnblogs.com/aziint/p/8416446.html
Copyright © 2020-2023  润新知