首页 > 代码库 > Desert King
Desert King
poj2728:http://poj.org/problem?id=2728
题意:给你n的点,每一个点会有一个坐标(x,y),然后还有一个z值,现在上你求一棵生成树,是的这棵生成树的所有边的费用/所有边的距离最小,其中,边费用是指两点之z差值的绝对值,边距离是指两点之间的距离。
题解:这一题就是求最小比率生成树。采用的解法就是0-1分数规划。
其中设最后的比率是l
1,z(l)是单调递减的。
2,z(max(l))=0;这可以采用反证法进行证明。
3,因为是完全图,所以要采用prime求最小生成树。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int N=1003; 8 const double inf=10000000000.0; 9 double mp[N][N],cost[N][N];10 double dist[N];11 double xx[N],yy[N],zz[N];12 int n;13 bool vis[N];14 bool solve(double x){15 for(int i=1;i<=n;i++){16 vis[i]=0;17 dist[i]=cost[i][1]-mp[i][1]*x;18 }19 vis[1]=1;20 dist[1]=0;21 double cost2=0;22 for(int i=1;i<n;i++){23 double minn=inf;24 int k=-1;25 for(int j=1;j<=n;j++){26 if(!vis[j]&&dist[j]<minn){27 minn=dist[j];28 k=j;29 }30 }31 if(k!=-1){32 cost2+=dist[k];33 vis[k]=1;34 for(int j=1;j<=n;j++){35 if(!vis[j]){36 double tt=cost[k][j]-mp[k][j]*x;37 if(dist[j]>tt){38 dist[j]=tt;39 }40 }41 }42 }43 }44 if(cost2>=0)return true;45 return false;46 47 }48 int main(){49 while(~scanf("%d",&n)&&n){50 for(int i=1;i<=n;i++){51 scanf("%lf%lf%lf",&xx[i],&yy[i],&zz[i]);52 }53 for(int i=1;i<=n;i++){54 for(int j=i+1;j<=n;j++){55 double temp=(xx[i]-xx[j])*(xx[i]-xx[j])+(yy[i]-yy[j])*(yy[i]-yy[j]);56 mp[i][j]=mp[j][i]=sqrt(temp);57 cost[i][j]=cost[j][i]=abs(zz[i]-zz[j]);58 }59 }60 double l=0,r=100,ans=0;61 while(abs(r-l)>1e-4){62 double mid=(r+l)/2;63 if(solve(mid)){64 l=mid;65 ans=mid;66 }67 else68 r=mid;69 }70 printf("%.3f\n",ans);71 }72 }
Desert King
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。