poj2728 二分优化

题目大意:

给你一堆三维的点,每个点之间的距离是xy轴的欧式距离,代价是高度,问一颗最优比例生成树。这题是我很早之前做过的了,当初还非常非常菜,给大家看一下我的情况。

当初可真是年少无知啊,这个prim因为是稠密图,所以n方才能求生成树,很神奇啊,稠密图的最小生成树算法居然是o(e)的,不过还是很慢就是了。

后来这个题还有一次二分优化,就是说你二分得到的知识不仅仅是只有能或者不能,而是还存在着其他的信息。

你二分了一次之后还能得到一些有用的,就是你能拿到下一次可能的答案。

你从下一次的答案还能继续递推,这样可以更快速的跳过去。

具体的可以去学学01规划,这个trick感觉还可以。

ac代码(快的那个):

#include <queue>
#include <math.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <cstring>
#include <stdio.h>
#define clr(a) memset(a,0,sizeof a)
using namespace std;
typedef pair<double ,int> P;
const int maxn=1000+10;
const int inf=0x3f3f3f3f;
double mm[maxn][maxn];
int n,heigh[maxn];
P m_t[maxn];
struct node
{
    double wei,dis,cos;
};
double dis(double a,double b,double c,double d)
{
    return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
bool used[maxn];
double J(double c)
{
    clr(used);
    node lowcast[maxn];
    for(int i=0;i<maxn;i++){
        lowcast[i].wei=inf;
    }
    lowcast[0].wei=0;
    lowcast[0].dis=0;
    lowcast[0].cos=0;
    double dis_sum=0,cost_sum=0;
    while(1)
    {
        int k=-1,t_max=inf;
        for(int i=0;i<n;i++)
        {
            if(!used[i]&&lowcast[i].wei<t_max)
            {
                t_max=lowcast[i].wei;
                k=i;
            }
        }
        if(k==-1)
            break;
        used[k]=1;
        cost_sum+=lowcast[k].cos;
        dis_sum+=lowcast[k].dis;
        for(int i=0;i<n;i++)
            if(!used[i]&&lowcast[i].wei>abs(heigh[k]-heigh[i])-c*mm[k][i]){
                lowcast[i].wei=abs(heigh[k]-heigh[i])-c*mm[k][i];
                lowcast[i].cos=abs(heigh[k]-heigh[i]);
                lowcast[i].dis=mm[k][i];
            }
    }
    return cost_sum/dis_sum;
}
int main()
{
    while(1){
        scanf("%d",&n);
        if(n==0)
            break;
        for(int i=0;i<n;i++)
            scanf("%lf%d%d",&m_t[i].first,&m_t[i].second,&heigh[i]);
        for(int i=0;i<n;i++)//n2
            for(int j=i;j<n;j++)
            {
                mm[j][i]=mm[i][j]=dis(m_t[i].first,m_t[i].second,m_t[j].first,m_t[j].second);
            }
        double rate=0,t_rate;
        while(1)
        {
            t_rate=J(rate);
            if(abs(t_rate-rate)<0.00001){
                rate=t_rate;
                break;
            }
            rate=t_rate;
        }
        printf("%.3lf
",rate);
    }
}
原文地址:https://www.cnblogs.com/King-of-Dark/p/12826289.html