原题: https://pintia.cn/problem-sets/994805046380707840/problems/994805049102811136
题意:
有n条竖线,给出位置和长度,你需要找出一条线,穿过所有的线(包括边界点)。要求线的两个顶点坐标为整数。
方法一:
三分在-1e6上的可行区域,check函数为:从这个点投出光,穿过每条线段后可能会遮挡一部分,判断是否有一丝光穿过所有线段。复杂度 。
但是找到这个区域后找两个整数点就比较麻烦了。
方法二:
发现不管怎么画,都可以通过微调答案线使之穿过至少一个上端点,一个下端点。所以我枚举每个上端点作为答案端点。
显然,对于引伸出的线,所有上端点都应该在其上方,所有下端点都在其下方。
- 为了使所有上端点在上面,对于左边的上端点,左边要往下压(类似于跷跷板),那么斜率越来越大;
- 对于右边的上端点,右边往下压,斜率越来越小;此时判断斜率是否小于左边的最大斜率,如果是,则说明不存在经过当前点的线,使所有点在其上方。
- 下端点类似,只不过左边往上斜率越来越小,右边往上斜率越来越大。
结束之后有:
- 任意满足比左上大,比右上小的斜率k,都可以使全部上端点处于上方;
- 比右下大,左下小的,所有下端点处于其下方;
- 此时若有一个k同时满足这两个条件,就是答案。
复杂度 。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+4;
struct node{
float x,Y,y;
bool operator<(const node &r)const{
return x<r.x;
}
}e[maxn];
int main(){
int n;scanf("%d",&n);
for(register int i=1;i<=n;i++)
scanf("%f%f%f",&e[i].x,&e[i].Y,&e[i].y);
if(n==1){
return 0*printf("%.0f %.0f %.0f %.0f\n",e[1].x,e[1].Y,e[1].x+1,e[1].Y);
}
sort(e+1,e+1+n);
for(register int i=1;i<=n;i++){
float upl=-1e9,upr=1e9,downl=1e9,downr=-1e9;
int p1=-1,p2=-1,p3=-1,p4=-1;
int can=1;
for(register int j=1;j<i;j++){
if(upl<(e[i].Y-e[j].Y)/(e[i].x-e[j].x))
upl=(e[i].Y-e[j].Y)/(e[i].x-e[j].x),p1=j;
}
for(register int j=i+1;j<=n;j++){
if(upr>(e[i].Y-e[j].Y)/(e[i].x-e[j].x)){
upr=(e[i].Y-e[j].Y)/(e[i].x-e[j].x),p2=j;
if(upr<upl)
{can=0;break;}
}
}
if(!can)continue;
for(register int j=1;j<i;j++){
if(downl>(e[i].Y-e[j].y)/(e[i].x-e[j].x))
downl=(e[i].Y-e[j].y)/(e[i].x-e[j].x),p3=j;
}
for(register int j=i+1;j<=n;j++){
if(downr<(e[i].Y-e[j].y)/(e[i].x-e[j].x)){
downr=(e[i].Y-e[j].y)/(e[i].x-e[j].x),p4=j;
if(downr>downl)
{can=0;break;}
}
}
if(!can)continue;
if(downl>=upr&&upr>=downr&&p2>0){
return 0*printf("%.0f %.0f %.0f %.0f\n",e[i].x,e[i].Y,e[p2].x,e[p2].Y);
}
else if(downl>=upl&&downl<=upr&&p3>0){
return 0*printf("%.0f %.0f %.0f %.0f\n",e[i].x,e[i].Y,e[p3].x,e[p3].y);
}
else if(downr>=upl&&downr<=upr&&p4>0){
return 0*printf("%.0f %.0f %.0f %.0f\n",e[i].x,e[i].Y,e[p4].x,e[p4].y);
}
else if(upl>=downr&&upl<=downl&&p1>0){
return 0*printf("%.0f %.0f %.0f %.0f\n",e[i].x,e[i].Y,e[p1].x,e[p1].Y);
}
}
}