wu


私信TA

用户名:cncfvc

访问量:215388

签 名:

读研狗没有时间刷题了~~

等  级
排  名 2
经  验 36025
参赛次数 8
文章发表 265
年  龄 25
在职情况 学生
学  校 电子科技大学
专  业 通信工程

  自我简介:

写代码 真好玩 ~

解题思路:

这题有一定的难度  
需要一定的时间来理解


参考代码:

#include<iostream>  
#include<algorithm>  
#include<cstdio>  
#include<cmath>  
using namespace std;  
  
const int N=100000;  
struct P{int x,y;};  
bool cmp(P a,P b){  
    if(a.x==b.x)return a.y<b.y;  
    return a.x<b.x;  
}  
P d[N+5];  
struct F{int max,min;};  
F fl[N+5],fr[N+5];  
inline double Max(double a,double b){return a>b?a:b;}  
inline double Min(double a,double b){return a>b?b:a;}  
bool check(double m,int n){  
    m*=2;  
    int i,j=0;  
    for(i=0;i<n;i++){  
        while(j<n&&d[j].x-d[i].x<=m)j++;  //找出最大的xj使xj-xi<=m,所以在xi到xj的这段区间的范围
是垂直线的范围之后找出[1,i-1]以及[j+1,n-1]范围内的最大的y和最小的y值,如果最大的y值减去最小的y值<=m,
则说明这是水平线的范围,则进行下一轮二分找出中点,找出更优解。
        double MAX=-1e10;  
        double MIN=1e10;  
        if(j!=n){  
            MAX=Max(MAX,fr[j].max);  
            MIN=Min(MIN,fr[j].min);  
        }  
        if(i-1>=0){  
            MAX=Max(MAX,fl[i-1].max);  
            MIN=Min(MIN,fl[i-1].min);  
        }  
     //   cout<<i<<" "<<j<<" "<<MAX<<" "<<MIN<<endl;  
        if(MAX-MIN<=m)return true;  
    }  
    return false;  
}  
void init(int n){  
    int i;  
    fl[0].min=fl[0].max=d[0].y;  
    for(i=1;i<n;i++){  
        fl[i].max=Max(fl[i-1].max,d[i].y); //fl[i]代表着前i个y坐标里面的最大值, 
        fl[i].min=Min(fl[i-1].min,d[i].y); //fl[i]代表着前i个y坐标里面的最小值。 
    }  
    fr[n-1].min=fr[n-1].max=d[n-1].y;  
    for(i=n-2;i>=0;i--){  
        fr[i].max=Max(fr[i+1].max,d[i].y); //fr[i]代表着后(n-i)个y坐标里面的最大值 
        fr[i].min=Min(fr[i+1].min,d[i].y);  //fr[i]代表着后(n-i)个y坐标里面的最小值 
    }  
}  
int main(){  
    int i,n;  
    cin>>n;  
    for(i=0;i<n;i++){  
        int x,y;  
        scanf("%d%d",&x,&y);  
        d[i].x=x+y;   
        d[i].y=x-y;  //将坐标轴按顺时针旋转45度。 
    }  
    sort(d,d+n,cmp);  //按x坐标从小到大的顺序排序 
    init(n);  
    double l=0.0;  
    double r=1000000000;  
    while(r-l>=0.01){  
        double m=(l+r)/2; //二分法判断答案
      //  cout<<m<<endl;  
        if(check(m,n))r=m;  
        else l=m;  
    }  
    printf("%.1f\n",r);  //分到不能再分之后 得出答案即为最小的最大的曼哈顿距离
    return 0;  
}


 

0.0分

4 人评分

  评论区

请问有详解吗?
2019-11-11 14:07:20
  • «
  • 1
  • »