您的位置:首页 > 其它

POJ 2728 Desert King(最优比率生成树) prim+二分

2013-07-27 21:38 246 查看


POJ 2728 Desert King(最优比率生成树) prim+二分

北京赛区的经典题目,最优比率生成树,传说中楼哥1A的G题。。。

什么是最优比率生成树呢?说白了很简单,已知一个完全图,每条边有两个参数(b和c),求一棵生成树,使(∑xi×ci)/(∑xi×bi)最小,其中xi当第i条边包含在生成树中时为1,否则为0。其实也可以看成一个0,1的整数规划问题。

我的做法是LRJ《算法艺术与信息学竞赛》中介绍的二分,详细的证明请看书,这里只是简单的介绍一下核心的方法:

1.首先找出这个比率的最小值和最大值 front,rear

2.求mid=(front+reat)/2

3.用 ci-mid*bi 重新构图

4.求出新图的最小生成树权值之和

5.如果权值等于0,mid就是我们要求的比率,结束。如果权值>0,front=mid,如果权值<0,rear=mid,跳回2继续循环。

不过这个算法对精度的要求比较高,我用0.001就错了,0.00001超时,只有0.0001AC,汗

另外时间效率也不高,3000MS的题,耗去了2500MS,看来这个算法还是有待改进。

下面是我的代码:


#include<iostream>


#include<algorithm>


#include<cstring>


#include<cmath>


using namespace std;


#define MAX 1001


#define INF 1000000000


struct node


{




double x,y,h;


}dot[MAX];






inline double dis(double x1,double y1,double x2,double y2)


{




return sqrt( (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1) );


}






double graph[MAX][MAX];




inline void creat(int n,double l)


{


int i,j;


for(i=1;i<=n;i++)


{




for(j=1;j<=n;j++)


{




graph[i][j]=fabs(dot[i].h-dot[j].h)-l*dis(dot[i].x,dot[i].y,dot[j].x,dot[j].y);


}


}


}




inline double prim(double graph[MAX][MAX],int n)


{


bool visit[MAX]={0};


int mark;


double dis[MAX];


double ans=0;


int i,j;


visit[1]=true;


for(i=1;i<=n;i++)


dis[i]=graph[1][i];


for(i=1;i<n;i++)


{




int minnum=INF;


for(j=1;j<=n;j++)


{




if(!visit[j]&&dis[j]<=minnum)


{


minnum=dis[j];


mark=j;


}


}


visit[mark]=true;


ans+=dis[mark];


for(j=1;j<=n;j++)


{


if(!visit[j]&&graph[mark][j]<dis[j])


dis[j]=graph[mark][j];


}




}


return ans;


}






int main()


{




int i,j;


int n;


double res;


while(scanf("%d",&n))


{




if(n==0)


break;


for(i=1;i<=n;i++)


{


scanf("%lf%lf%lf",&dot[i].x,&dot[i].y,&dot[i].h);


}


double front,rear;


front=0;


rear=100;//这个地方有点悬。。。


double mid;


double pre=0.0;


while(front<=rear)


{




mid=(front+rear)/2;


creat(n,mid);


res=prim(graph,n);


if(fabs(res-pre)<=0.0005)


break;


else if(res>0.0005)


front=mid;


else


rear=mid;


}


printf("%.3lf\n",mid);


}


return 0;


}

———————————————————————传说中的分割线————————————————————————————

终于在今天下午 使用迭代法将此题优化到282MS,呵呵 这名字让我又想起了数值分析。。。


#include<iostream>


#include<algorithm>


#include<cstring>


#include<cmath>


using namespace std;


#define MAX 1001


#define INF 1000000000


struct node


{


double x,y,h;


}dot[MAX];






inline double dis(double x1,double y1,double x2,double y2)


{




return sqrt( (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1) );


}






double graph[MAX][MAX];


double c[MAX][MAX];


double s[MAX][MAX];




inline void creatcs(int n)


{


int i,j;


for(i=1;i<=n;i++)


{


for(j=1;j<=n;j++)


{


c[i][j]=fabs(dot[i].h-dot[j].h);


s[i][j]=dis(dot[i].x,dot[i].y,dot[j].x,dot[j].y);


}


}


}






inline void creat(int n,double l)


{


int i,j;


for(i=1;i<=n;i++)


{




for(j=1;j<=n;j++)


{




graph[i][j]=c[i][j]-l*s[i][j];


}


}


}


double sumc;


double sums;




inline void prim(double graph[MAX][MAX],int n)


{


sumc=0;


sums=0;


bool visit[MAX]={0};


int mark;


int pre[MAX];


double dis[MAX];


int i,j;


visit[1]=true;


for(i=1;i<=n;i++)


{


dis[i]=graph[1][i];


pre[i]=1;


}


for(i=1;i<n;i++)


{




int minnum=INF;


for(j=1;j<=n;j++)


{




if(!visit[j]&&dis[j]<=minnum)


{


minnum=dis[j];


mark=j;


}


}


visit[mark]=true;


sumc+=c[pre[mark]][mark];


sums+=s[pre[mark]][mark];


for(j=1;j<=n;j++)


{


if(!visit[j]&&graph[mark][j]<dis[j])


{


dis[j]=graph[mark][j];


pre[j]=mark;


}


}




}


}






int main()


{




int i,j;


int n;


while(scanf("%d",&n))


{




if(n==0)


break;


for(i=1;i<=n;i++)


{


scanf("%lf%lf%lf",&dot[i].x,&dot[i].y,&dot[i].h);


}


creatcs(n);


double prerate=30.0;


double rate=30.0;


while(true)


{


creat(n,rate);


prim(graph,n);


rate=sumc/sums;


if(fabs(rate-prerate)<0.001)


break;


prerate=rate;


}


printf("%.3lf\n",rate);


}


return 0;


}

posted on 2009-09-04 23:53 abilitytao 阅读(2116) 评论(4) 编辑 收藏 引用


最优比例生成树

My mathematics homework here :)

















tags:

最优比例 生成树 最小生成树 支撑树 best radio spanning tree (BRST)

算法艺术与信息学竞赛 刘汝佳 lrj acm

二分枚举答案 参数搜索 01分数规划问题转换 二分法 单调
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: