AtCoder Beginner Contest 220 G - Isosceles Trapezium(计算几何+map)
题意
给N个点,每一个点有一个权值,找一个顶点权值和最大的等腰梯形。(\(1\leq N\leq 1000\))
做法
非常巧妙地运用了等腰梯形的一个性质:上底的中垂线与下底的中垂线重合,于是可以枚举出任意两点的中垂线,然后找中垂线上权值最大的两个点。
比较好写的写法就是map套map,但我自己写了半天都在报错,最后就抄网上的大佬写的。
代码
/*************************************************************************
> File Name: 1.cpp
> Author: Knowledge_llz
> Mail: 925538513@qq.com
> Blog: https://www.cnblogs.com/Knowledge-Pig/
> Created Time: 2021/9/15 18:40:30
************************************************************************/
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define LL long long
#define pb push_back
#define pr pair<LL, LL>
#define endl '\n'
using namespace std;
LL n, ans = -1, x[1005], y[1005], c[1005];
map<tuple<LL, LL, LL>, map<pair<LL, LL>, LL>> M;
int main(){
ios::sync_with_stdio(false); cin.tie(0);
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
freopen("output.out","w", stdout);
#endif
cin >> n;
for(int i = 1; i <= n; ++i) cin >> x[i] >> y[i] >> c[i];
for(int i = 1; i <= n; ++i)
for(int j = i + 1; j <= n; ++j){
LL px = x[j] - x[i], py = y[j] - y[i], midx = x[j] + x[i], midy = y[j] + y[i];
LL g = __gcd(px, py);
px /= g; py /= g;
if(px < 0 || (!px && py < 0)) px = -px, py = -py;
auto &line = M[{px, py, midx * px + midy * py}];
line[pr(midx, midy)] = max(line[pr(midx, midy)], c[i] + c[j]);
}
for(auto line : M){
pr tmp(0, 0);
for(auto point : line.second){
if(tmp.first > tmp.second) tmp.second = max(tmp.second, point.second);
else tmp.first = max(tmp.first, point.second);
}
if(tmp.first > 0 && tmp.second > 0) ans = max(ans, tmp.first + tmp.second);
}
cout << ans << endl;
return 0;
}