现在的位置: 首页 > 综合 > 正文

POJ2728 Desert King

2017年04月28日 ⁄ 综合 ⁄ 共 1947字 ⁄ 字号 评论关闭

题目大意呢。。。

很多村庄&&一个王堡,王堡有水,村庄没水,可以修水渠,

两地之间修水渠的价格就是两地海拔差,长度就是水平距离

要求总花费:总长度尽量小,且一个村庄只有一条连向王堡的路。。

规定1号就是王堡

输入多组数据

开头N

然后N个x y z,表示横坐标 纵坐标,海拔高

如果N=0输入结束~~

输出最小比率,保留三位小数。。

传说中楼爷25minAC的题目,,我果断花了一天的时间

改的天昏地暗,各种优化。。。

最后发现错误是%.3f与%.3lf的不同(想不清啊。。。。)

思路:

很明显的最优比率啊,,

PS:(最优比率生成树可参考我滴另一篇文章~~自认为还行~~)

附链接:http://blog.csdn.net/loriex/article/details/18980625

我们有两种做法:

1.题意也就是总长度:总花费尽量大,那么长度是价值,花费是价格,

可以直接套用我之前写的最优比率生成树的思路,最后只要输出答案的倒数~~

(PS:我写的是妥妥的超时了。。按理说应该不至于,,可能我太渣了。。。哭

不过由于%.3lf的缘故我写了又改成了第二种思路大哭

2.只要理解了最优比率生成树的做法,,这道题也可以类似推出啊。。

我们假设花费=l*长度

然后边权=花费-mid*长度

然后为了使l尽量小,我们选择用最小生成树

(为什么用最小生成树??可以参考我的另一篇文章讲最优比率生成树的,

根据那个为什么用最大生成树的相同思路可以得解)

然后不断2分就可以得解了。。。

由于%.3lf WA了很多次

所以我的代码几乎是高仿别人的。。。(为了找错。。。)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
#define INF 1000000000
#define MAX 1001
struct node
{
	int x;
	int y;
	int z;
}; 
node vill[MAX];
double dista[MAX][MAX],hengh[MAX][MAX],map[MAX][MAX],minmap[MAX];
bool vis[MAX];
int n;
double dis(int a,int b)
{//计算ab之间的距离 
	return sqrt((vill[a].x-vill[b].x)*(vill[a].x-vill[b].x)+(vill[a].y-vill[b].y)*(vill[a].y-vill[b].y));
}
void init()
{
	for (int i = 1; i <= n; i++)
	{ 
		scanf("%d%d%d",&vill[i].x,&vill[i].y,&vill[i].z);
	}
	for (int i = 1; i <= n; i++)
	for (int j = i+1; j <= n; j++)
	{
		dista[j][i] = dista[i][j] = dis(i,j);
		hengh[j][i] = hengh[i][j] = abs(vill[i].z - vill[j].z);
	}//hengh是海拔差,dista是长度 
}
void create(double l)
{//建图 
	for (int i = 1; i <= n; i++)
	for (int j = i+1; j <= n; j++)
	{
		map[j][i] = map[i][j] = hengh[i][j] - l * dista[i][j];
	}
}
double prim(double dist[])
{//计算出最小生成树的权和 
    double ans =0;
    for (int i =1; i <= n; i++)
    {
	    dist[i] = INF,
		vis[i] = false;
    }
	dist[1] =0;
    while (1)
    {
        double mindist = INF;
        int mini =-1;
        for (int i = 1; i <= n; i++)
            if (dist[i] < mindist &&!vis[i])
            {
                mindist = dist[i];
                mini = i;
            }
        if (mini == -1 )
            return ans;
        vis[mini] =true;
        ans += mindist;
        for (int i = 1; i <= n; i++)
            if (!vis[i] && map[mini][i] < dist[i])
                dist[i] = map[mini][i];
    }
}
int main()
{
	while( scanf("%d",&n) && n > 0 )
	{
		init();
		double l = 0, r = 1000000000;
		while (r - l > 0.0001)
		{
		    double mid = (l + r) /2;
		    create(mid);
		    double temp = prim(minmap);
		    if (temp >=0)
				l = mid;
			else
				r = mid;
		}//不断二分得解 
		printf("%.3f\n",l);
	}
	return 0;
}

抱歉!评论已关闭.