B - Desert King 二分加prim

参考大佬的链接
题目戳我

对于只学了krukal的我来说太难了,花了一下午去学prim,我太菜了,先是模板简单题wa了两发,后来还是看题解找出的bug,我太难了我太难了我还是太菜了,连模板题写的这么艰难模板题目链接戳我
1对于本题来说题意是:国王想在他的领地上挖河道,覆盖全部的n个村庄,村庄与村庄之间不仅有水平距离的插值还有高度的差值,要你求让河流经过全部村庄的方案里高度差的绝对值的和/河流的总长度长度,的最小值。
题解:反正我没有想到过二分,只知道要用prim求,更离谱的是那个大佬说的那个二分题我还写过,我居然没有想到,惭愧,那么为什么可以那样二分呢,设mh为总的高度差的绝对值的和,mlen为总的长度那么,ans为答案,mh/mlen=ans;那么化简一下mh-ansmlen=0,那么对于h[i]-anslen[i](1<=i<=n)全部求和得到的segema(h[i]-anslen[i])=0;那么当ans偏大的时候segema(h[i]-anslen[i])<0,偏小的时候就会大于0,所有简单想一下应该是满足二分的.

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
//#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define lson num<<1
#define rson num<<1|1
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 3e5+ 50;
const double esp = 1e-6;
const int inf = 0x3f3f3f3f;
const ll  lnf  = 0x3f3f3f3f3f3f3f3f;
const ll mod = 23333;
const  double pi=3.141592653589;
int n,m,cnt,head[10005],vis[10005];//vis标记是否出现过
struct node
{
    int x,y,z;
}a[1005];
double mp[1005][1005];//(i,j)两点的距离
double dis[1005];//到达i点最小距离
double cost[1005][1005];
bool check(double mid)
{
    ms(vis,0);
    for(int i=1;i<=n;i++)dis[i]=(double)cost[1][i]-mid*mp[1][i];//表示1与其他点之间的距离
    double ans=0;
    vis[1]=1;
    for(int i=1;i<=n-1;i++)
    {
        double mi=inf;
        int pos=-1;
        for(int j=1;j<=n;j++)//找到没有相连过的点,并且是最小的那个点
        {
            if(!vis[j]&&mi>dis[j])
            {
                mi=dis[j];
                pos=j;
            }
        }
        ans+=mi;
        vis[pos]=1;
        for(int j=1;j<=n;j++)//更新每个点的距离
        {
            if(!vis[j]&&dis[j]>(double)cost[pos][j]-mid*mp[pos][j])
            {
                dis[j]=cost[pos][j]-mid*mp[pos][j];
            }
        }
    }
    return ans>=0;
}
int main()
{
    while(~scanf("%d",&n))
    {
        if(n==0)break;

        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<i;j++)
            {
                mp[i][j]=mp[j][i]=sqrt(1.0*(a[i].x-a[j].x)*(a[i].x-a[j].x)+1.0*(a[i].y-a[j].y)*(a[i].y-a[j].y));
                cost[j][i]=cost[i][j]=fabs(1.0*a[i].z-1.0*a[j].z);
            }
        }
        double l=0.0,r=100.0;
        while(fabs(r-l)>esp)
        {
            double mid=(l+r)/2;
            if(check(mid))
            {
               l=mid;
            }
            else
            {
                r=mid;
            }
        }
        printf("%.3f\n",r);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qcccc_/article/details/107387634
今日推荐