[BalkanOI 2007] Point

给了n个三维空间上的点,求出有多少条至少包含三点的直线。
因为n的上界为1000,所以允许 \(O(n^2)\) 的算法。
我们可以枚举两个点,记录这条直线。
然后用一个map存储共线的数量然后统计答案就行了。
相当没难度

#include<bits/stdc++.h>
#define gcd __gcd
using namespace std;
struct node{
	int x,y,z;
	friend bool operator <(node a,node b){return a.x^b.x?a.x<b.x:a.y^b.y?a.y<b.y:a.z<b.z;}
	friend bool operator >(node a,node b){return a.x^b.x?a.x>b.x:a.y^b.y?a.y>b.y:a.z>b.z;}
}a[1001];
void calc(int &dx,int &dy,int &dz) {
    int g=gcd(abs(dx),gcd(abs(dy),abs(dz)));
    if(!g)return;
    dx/=g,dy/=g,dz/=g;
    if(dx<0)dx=-dx,dy=-dy,dz=-dz;
    else if(!dx){
        if(dy<0)dy=-dy,dz=-dz;
        else if(!dy)if(dz<0)dz=-dz;
    }
}

int n,ans;
map<node,pair<int,int>>mp;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y>>a[i].z;
	for(int i=1;i<=n;i++){
		mp.clear();
		for(int j=1;j<=n;j++){
			if(i==j)continue;
			int dx=a[j].x-a[i].x;
			int dy=a[j].y-a[i].y;
			int dz=a[j].z-a[i].z;
            if(!dx&&!dy&&!dz)continue;
			calc(dx,dy,dz);
            node t={dx,dy,dz};
			if(mp.find(t)==mp.end())mp[t]=make_pair(1,j);
			else{
				mp[t].first++;
				if(j<mp[t].second)mp[t].second=j;
			}
		}
		for(auto &t:mp)if(t.second.first>1)if(t.second.second>i)ans++;
	}
	cout<<ans;
	return 0;
}

posted @ 2025-08-20 10:13  zhuoheng  阅读(7)  评论(0)    收藏  举报