P13667 [GCPC 2023] Balloon Darts
相当于找三条直线穿过所有点。
因为鸽巢原理,所以选取某 \(4\) 个点,其中必有两点共线。
我们可以枚举这条直线,然后将直线上的点删去。
在剩下的点中选取某 \(3\) 个点,其中必有两点共线。
同样枚举这条直线,然后将直线上的点删去。再判定剩下的点是否共线即可。
时间复杂度 \(O(n)\),有 \(\dbinom{4}{2}\times \dbinom{3}{2}=18\) 的常数。
点击查看代码
#include<bits/stdc++.h>
#define eb emplace_back
#define int long long
using namespace std;
const int N=1e4+5;
struct Pt{int x,y;}a[N];
inline int cross(Pt a,Pt b){return a.x*b.y-a.y*b.x;};
Pt operator - (Pt a,Pt b){return {a.x-b.x,a.y-b.y};}
int t,n;
vector<Pt> v,vv;
inline bool solve(){for(int i=0;i<4;i++){for(int j=i+1;j<4;j++){v.clear();for(int k=0;k<n;k++){if(cross(a[i]-a[j],a[k]-a[j])){v.eb(a[k]);}}int m=v.size();if(m<=4) return 1;for(int k=0;k<3;k++){for(int l=k+1;l<3;l++){vv.clear();for(int o=0;o<m;o++){if(cross(v[k]-v[l],v[o]-v[l])){vv.eb(v[o]);}}if(vv.size()<=2) return 1;int flg=1;for(Pt i:vv){if(cross(i-vv[0],i-vv[1])){flg=0;break;}}if(flg) return 1;}}}}return 0;
}
signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);t=1;while(t--){cin>>n;for(int i=0;i<n;i++) cin>>a[i].x>>a[i].y;if(n<=6) cout<<"possible\n";else cout<<(solve()?"possible\n":"impossible\n");}return 0;
}