标签:
| Time Limit: 3000MS | Memory Limit: 65536K | |
| Total Submissions: 21766 | Accepted: 6087 |
Description
Input
Output
Sample Input
4 0 0 0 0 1 1 1 1 2 1 0 3 0
Sample Output
1.000
题意:有n个村庄,分别给出每个村庄的地理坐标(xi,yi)和海拔hi,要求在村庄之间修一些河道,使这些河道联通所有的村庄,不同的村庄由于海拔的差异需要修水泵,每个水泵的费用为这两个村庄的海拔差值,且每个水泵为一条河道所用,要求所有的费用/总的河道长度比率最小
分析:r=sigma(h[i][j])/sigma(l[i][j]),设R为最优值,则r>=R;(h[i][j]代表修每条河道的费用,l[i][j]代表每条河道的长度,sigma()为生成树里面的边)
即:sigma(h[i][j])/sigma(l[i][j])>=R,所以:h[r]=sigma(h[i][j])-r*sigma(l[i][j])>=0;
所以对于每一个r对应的h(r)的最小生成树>=0
当h(r)<0的时候减小r的值,否则增大r的值,逐渐二分使h(r)=0即可;
方法一:二分法
#include"stdio.h"
#include"string.h"
#include"math.h"
#define inf 0x3f3f3f3f
#define M 2009
#define eps 1e-7
struct node
{
int x,y,h;
}p[M];
double dist(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y));
}
double dis[M],G[M][M],L[M][M];
int use[M];
double dij(int n,int s)
{
double sum=0;
memset(use,0,sizeof(use));
for(int i=1;i<=n;i++)
dis[i]=inf;
dis[s]=0;
for(int i=1;i<=n;i++)
{
double mini=inf;
int id=-1;
for(int j=1;j<=n;j++)
{
if(!use[j]&&dis[j]<mini)
{
mini=dis[j];
id=j;
}
}
if(id==-1)break;
sum+=dis[id];
use[id]=1;
for(int j=1;j<=n;j++)
{
if(!use[j]&&dis[j]>G[id][j])
dis[j]=G[id][j];
}
}
return sum;
}
double solve(int n,double r)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
G[i][j]=G[j][i]=fabs(p[i].h*1.0-p[j].h*1.0)-L[i][j]*r+1000000000.0;
}
return dij(n,1)-(n-1)*1000000000.0;
}
int main()
{
int n;
while(scanf("%d",&n),n)
{
double l=0,r=0,mid;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].h);
r+=p[i].h;
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
L[i][j]=L[j][i]=dist(p[i],p[j]);
}
}
while(r-l>eps)
{
mid=(l+r)/2;
double msg=solve(n,mid);
if(msg<0)
{
r=mid;
}
else
{
l=mid;
}
}
printf("%.3lf\n",r);
}
return 0;
}
方法二:迭代法
#include"stdio.h"
#include"string.h"
#include"math.h"
#define inf 0x3f3f3f3f
#define M 2009
#define eps 1e-6
struct node
{
int x,y,h;
}p[M];
double dist(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y));
}
double dis[M],G[M][M],L[M][M];
int use[M],pre[M];
double dij(int n,int s)
{
double sum=0,cost=0,leng=0;
memset(use,0,sizeof(use));
for(int i=1;i<=n;i++)
{
dis[i]=inf;
pre[i]=-1;
}
dis[s]=0;
for(int i=1;i<=n;i++)
{
double mini=inf;
int id=-1;
for(int j=1;j<=n;j++)
{
if(!use[j]&&dis[j]<mini)
{
mini=dis[j];
id=j;
}
}
if(id==-1)break;
sum+=dis[id];
use[id]=1;
if(pre[id]!=-1)
{
cost+=fabs(p[id].h*1.0-p[pre[id]].h);
leng+=L[id][pre[id]];
}
for(int j=1;j<=n;j++)
{
if(!use[j]&&dis[j]>G[id][j])
{
dis[j]=G[id][j];
pre[j]=id;
}
}
}
return cost/leng;
}
double solve(int n,double r)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
G[i][j]=G[j][i]=fabs(p[i].h*1.0-p[j].h*1.0)-L[i][j]*r+1000000000.0;
}
}
return dij(n,1);
}
int main()
{
int n;
while(scanf("%d",&n),n)
{
for(int i=1;i<=n;i++)
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].h);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
L[i][j]=L[j][i]=dist(p[i],p[j]);
double x0=0,x;
while(1)
{
x=solve(n,x0);
if(fabs(x-x0)<eps)
break;
x0=x;
}
printf("%.3lf\n",x);
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/mypsq/p/4469554.html