[题解]P13667 [GCPC 2023] Balloon Darts

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;
}
posted @ 2025-10-29 07:16  Sinktank  阅读(6)  评论(0)    收藏  举报
★CLICK FOR MORE INFO★ TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2025 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.