【POJ 2728】Desert King (最优比例生成树)
这是一道01分数规划之最优比例生成树的入门题
类似的 我们对于每次check 预处理d数组(代码里是lowcost[])由于是稠密图 跑一遍prim
由于prim就是通过贪心,保证每次选的边最优来做的,所以只用统计最小生成树的权值有没有大于0
#include<iostream> #include<cstring> #include<cmath> #include<iomanip> #define N 1005 #define eps 1e-6 #define INF 0x7fffffff using namespace std; int n; double x[N],y[N],z[N],dis[N][N],cost[N][N],lowcost[N]; bool vis[N]; inline bool check(double a) { memset(lowcost,0,sizeof(lowcost)); memset(vis,false,sizeof(vis)); double sum=0; int pos=-1; vis[1]=true; for(int i=1;i<=n;i++) lowcost[i]=cost[1][i]-a*dis[1][i]; for(int i=1;i<n;i++) { double minv=INF; for(int j=1;j<=n;j++) { if(!vis[j]&&lowcost[j]<minv) { pos=j; minv=lowcost[j]; } } vis[pos]=true; sum+=minv; for(int j=1;j<=n;j++) { if(!vis[j]&&cost[pos][j]-a*dis[pos][j]<lowcost[j]) lowcost[j]=cost[pos][j]-a*dis[pos][j]; } } if(sum>=0) return true; else return false; } int main() { while(cin>>n&&n) { memset(x,0,sizeof(x)); memset(y,0,sizeof(y)); memset(z,0,sizeof(z)); memset(dis,0,sizeof(dis)); memset(cost,0,sizeof(cost)); for(int i=1;i<=n;i++) cin>>x[i]>>y[i]>>z[i]; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { dis[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); cost[i][j]=fabs(z[i]-z[j]); } } double l=0,r=1000; while(l+eps<r) { double m=(l+r)/2; if(check(m)) l=m; else r=m; } cout<<fixed<<setprecision(3)<<l<<'\n'; } return 0; }
QQ40523591~欢迎一起学习交流~