0/1分数规划
求下式的最大值:
也就是 对任意的x
二分一个值mid 问题转化是否存在一组x 使
如果存在 说明二分的值小了 如果不存在 说明二分的值大了
所以一求上面式子的最大值即可
这是0/1分数规划问题的关键: 求出满足题意的最大值
最优比例生成树
每个边有连个权值 求最优比例生成树
沙漠之王
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int N=1010;
const int INF=0x3f3f3f3f;
const double eps=1e-6;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
int n;
struct Point
{
int x,y,h;
}p[N];
double a[N][N],b[N][N],e[N][N];
double getdis(int x,int y,int x_,int y_){ return sqrt( (x-x_)*(x-x_)+(y-y_)*(y-y_) ); }
double dis[N];
bool vis[N];
//稠密图还真的不能加堆优化 加上堆优化后变成mlogn prim的优势不再显著
//double:: 1e37
bool check(double mid)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
e[i][j]=a[i][j]-mid*b[i][j];
for(int i=1;i<=n;i++) dis[i]=INF,vis[i]=0;
dis[1]=0;
for(int i=1;i<=n;i++)
{
int x=0;
for(int j=1;j<=n;j++)
if(!vis[j]&&(!x||dis[j]<dis[x])) x=j;//这种查找方式一定要处理第一次查找的情况
vis[x]=1;
for(int j=1;j<=n;j++)
if(!vis[j]) dis[j]=min(dis[j],e[x][j]);
}
double ret=0;
for(int i=1;i<=n;i++) ret+=dis[i];
return ret<0;
}
int main()
{
while( (n=read())!=0)
{
for(int i=1;i<=n;i++) p[i].x=read(),p[i].y=read(),p[i].h=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
a[i][j]=abs(p[i].h-p[j].h);
b[i][j]=getdis(p[i].x,p[i].y,p[j].x,p[j].y);
}
double l=0,r=1e11;
while(r-l>eps)
{
double mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid;
}
printf("%.3lf\n",r);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效