最优解必定过两个线段的端点
枚举其中一个,然后把其他所有端点相对枚举点极角排序,前缀和扫一遍就完了
Code:
#include<bits/stdc++.h>
#define ll long long
#define db double
#define eps 1e-8
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=2005;
int n,ans,tot;
struct line{int x1,x2,y,len;}a[N];
struct slp{db k;int kd;}b[N<<1];
bool operator<(slp a,slp b){return a.k<b.k;}
inline void solve(db x,db y){
int cnt=0;
for(int i=1;i<=n;i++){
if(a[i].y==y) continue;
b[++cnt].k=(a[i].x1-x)/(a[i].y-y);
b[++cnt].k=(a[i].x2-x)/(a[i].y-y);
if(b[cnt].k>b[cnt-1].k){
b[cnt-1].kd=a[i].len;
b[cnt].kd=-a[i].len;
b[cnt].k+=eps;
}
else{
b[cnt].kd=a[i].len;
b[cnt-1].kd=-a[i].len;
b[cnt-1].k+=eps;
}
}
sort(b+1,b+cnt+1);
for(int i=1;i<=cnt;i++){tot+=b[i].kd;ans=max(ans,tot);}
}
int main(){
n=read();ans=0;
for(int i=1;i<=n;i++){
a[i].x1=read();a[i].x2=read();a[i].y=read();
if(a[i].x1>a[i].x2) swap(a[i].x1,a[i].x2);
a[i].len=a[i].x2-a[i].x1;
}
for(int i=1;i<=n;i++){
tot=a[i].len;solve(a[i].x1,a[i].y);
tot=a[i].len;solve(a[i].x2,a[i].y);
ans=max(ans,tot);
}
cout<<ans;
return 0;
}