对于只学了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;
}