• POJ2728 Desert King


    一道生成树+(0/1)分数规划

    原题链接

    设每条边的距离为(dis[x]),两点高度差为(h[x]),该图的生成树为(T),则题目实际求的就是(dfrac{sumlimits_{xin T}h[x]}{sumlimits_{xin T}dis[x]})的最小值。
    这就是经典的(0/1)分数规划问题。
    这里我用的是二分法。二分答案,记为(mid)。将图上的边权全部改为(h[x]-mid imes dis[x]),然后在上面跑最小生成树并计算边权和,如果非负说明(mid)过小,否则过大。
    另外,虽然理论二分上界为(10^7),不过数据水,上界开四五十基本就能过了。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int N = 1010;
    struct dd {
    	int x, y, z;
    };
    dd a[N];
    int n;
    double D[N][N], dis[N];
    bool v[N];
    int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c<'0' || c>'9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0'&&c <= '9'; c = getchar())
    		x = x * 10 + (c - '0');
    	return p ? -x : x;
    }
    inline double minn(double x, double y)
    {
    	return x < y ? x : y;
    }
    inline int jd(int x)
    {
    	return x < 0 ? -x : x;
    }
    inline double co(int x, int y, double mid)
    {
    	return -mid * D[x][y] + jd(a[x].z - a[y].z);
    }
    double judge(double mid)
    {
    	double s = 0;
    	int i, j, x;
    	memset(v, 0, sizeof(v));
    	memset(dis, 66, sizeof(dis));
    	dis[1] = 0;
    	for (i = 1; i <= n; i++)
    	{
    		x = 0;
    		for (j = 1; j <= n; j++)
    			if (!v[j] && (dis[j] < dis[x] || !x))
    				x = j;
    		if (!x)
    			break;
    		v[x] = 1;
    		s += dis[x];
    		for (j = 1; j <= n; j++)
    			if (!v[j])
    				dis[j] = minn(dis[j], co(x, j, mid));
    	}
    	return s;
    }
    int main()
    {
    	int i, j;
    	double l, r, mid;
    	while (1)
    	{
    		n = re();
    		if (!n)
    			return 0;
    		for (i = 1; i <= n; i++)
    		{
    			a[i].x = re();
    			a[i].y = re();
    			a[i].z = re();
    		}
    		for (i = 1; i < n; i++)
    			for (j = i + 1; j <= n; j++)
    				D[i][j] = D[j][i] = sqrt(1.0*(a[i].x - a[j].x)*(a[i].x - a[j].x) + 1.0*(a[i].y - a[j].y)*(a[i].y - a[j].y));
    		l = 0;
    		r = 1e7;
    		while (l + 1e-4 < r)
    		{
    			mid = (l + r) / 2;
    			if (judge(mid) >= 0)
    				l = mid;
    			else
    				r = mid;
    		}
    		printf("%.3f
    ", l);
    	}
    	return 0;
    }
    
  • 相关阅读:
    游戏《翻转方块》小攻略
    净捡软柿子捏--jQuery 遍历方法
    关于兼容
    sublime
    jQuery中json对象与json字符串互换
    css之IE透明度
    关于优化
    html5+css+div随时笔记
    css3学习--border
    JavaScript学习1
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9573231.html
Copyright © 2020-2023  润新知