2036. Intersect Until You're Sick of It
题目连接:
http://acm.timus.ru/problem.aspx?space=1&num=2036
Description
Ural contests usually contain a lot of geometry problems. Many participants do not conceal their discontent with such disbalance. Still, we have decided not to break the tradition and give you an unbalanced contest. Let’s start!
Consider an iterative process for a set of points on a plane. Every iteration consists of three steps:
Draw a line through every pair of different points.
Find all intersections of all pairs of different non-parallel lines.
Merge the initial set of points with the set of intersection points and go to step one.
After each iteration, the number of points either increases or stays the same.
You are given a set of points. Iterations repeat while the number of points increases. How many points will be in the set after the end of this iterative process?
Input
The first line contains an integer n (1 ≤ n ≤ 100000). Further input describes n different points. For every point, you are given a pair of integer coordinates whose absolute value does not exceed 108.
Output
If the process is infinite, print “oo” (two lowercase Latin letters ‘o’), otherwise print the number of points in the set after the end of the process.
Sample Input
4
0 0
0 1
1 0
1 1
Sample Output
5
Hint
题意
给你n个点,然后进行下列操作:
1.两两点连线
2.找到所有不平行直线所构成的交点
3.把所有找到的点和原来的点合并,如果点数增加,再进行1操作;否则break
输出最后点的数量。
可能是无限多。
题解:
无限多的情况很多,我们来考虑特殊情况,即有解的:
显然所有点都是在一条直线上,这个答案是n
显然如果只有一个点不在直线上,这个答案也是n
有两个点不在直线上,那么答案可能是n,也有可能是n+1.
基本上情况就这些了,讨论一下,然后求解即可。
数据:
Anti-WA #51:
4
0 0
2 0
1 1
1 2
Answer: oo
Anti-WA #52:
4
0 0
1 2
2 2
3 0
Answer: oo
代码
#include <bits/stdc++.h>
using namespace std;
const int N=100010;
const int inf=1e9;
struct POINT
{
long long x;
long long y;
POINT(long long a=0, long long b=0) { x=a; y=b;} //constructor
bool operator<(const POINT &A)const{
if(A.x==x)return A.y<y;
return A.x<x;
}
};
long long multiply(POINT sp,POINT ep,POINT op)
{
return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
}
long long multiply(POINT A,POINT B,POINT C,POINT D)
{
long long x1 = A.x-B.x;
long long y1 = A.y-B.y;
long long x2 = C.x-D.x;
long long y2 = C.y-D.y;
return x1*y2-x2*y1;
}
POINT P[N];
int n;
int solve(POINT st)
{
vector<POINT> ans,ret;
if(st.x==0&&st.y==0)
{
return inf;
}
for(int i=1;i<=n;i++)
{
if(multiply(P[i],st,P[1])!=0) ans.push_back(P[i]);else ret.push_back(P[i]);
}
if(ans.size()<=1)
{
return n;
}
else
{
for(int i=2;i<ans.size();i++)
if(multiply(ans[0],ans[1],ans[i])!=0) return inf;
for(int i=0;i<ret.size();i++)
if(multiply(ret[i],ans[1],ans[0])==0)
return n;
if(ans.size()>2)
{
return inf;
}
else
{
long long t1=multiply(ans[0],st,P[1]),t2=multiply(ans[1],st,P[1]);
if(t1>0&&t2>0||t1<0&&t2<0)
{
return inf;
}
else
{
POINT pp;
int flag=1,f1=1,f2=1;
for(int i=0;i<ret.size();i++)
{
if(multiply(ret[i],ans[1],ans[0])<0) f1=0;
if(multiply(ret[i],ans[1],ans[0])>0) f2=0;
}
if(f1||f2) flag=0;
return n+flag;
}
}
}
}
long long X(POINT A,POINT B){
return A.x*B.y-A.y*B.x;
}
long long sq(long long A){
return A*A;
}
long long dis(POINT A,POINT B){
return sq(A.x-B.x)+sq(A.y-B.y);
}
bool ok4(){
long long tmp = multiply(P[1],P[2],P[3],P[4]);
if(tmp!=0)return 0;
tmp = multiply(P[1],P[2],P[3]);
if(tmp==0)return 0;
long long dis1 = dis(P[1],P[2]);
long long dis2 = dis(P[3],P[4]);
if(dis1!=dis2)return 0;
return 1;
}
bool ok14(){
long long tmp = multiply(P[1],P[2],P[3]);
if(tmp==0)return 1;
long long dis1 = dis(P[1],P[2]);
long long dis2 = dis(P[3],P[4]);
if(dis1==dis2)return 1;
return 0;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%I64d%I64d",&P[i].x,&P[i].y);
}
for(int i=2;i<=n;i++)
P[i].x-=P[1].x,P[i].y-=P[1].y;
P[1].x=P[1].y=0;
int tmp=inf;
if(n<=3)
{
printf("%d
",n);
return 0;
}
if(n==4){
sort(P+1,P+1+n);
do{
if(ok4()){
printf("5
");
return 0;
}
}while(next_permutation(P+1,P+1+n));
sort(P+1,P+1+n);
do{
if(ok14()){
printf("4
");
return 0;
}
}while(next_permutation(P+1,P+1+n));
printf("oo
");
return 0;
}
if(n<=5)
{
for(int o=2;o<=n;o++)
{
tmp=min(tmp,solve(P[o]));
}
}
else
{
int flag=0;
POINT stt;
stt.x=stt.y=0;
for(int i=2;i<=6;i++)
{
for(int j=i+1;j<=6;j++)
{
for(int k=j+1;k<=6;k++)
if(multiply(P[i],P[j],P[1])==0&&multiply(P[i],P[k],P[1])==0)
{
stt=P[i];
flag=1;
break;
}
if(flag) break;
}
if(flag) break;
}
tmp=solve(stt);
}
if(tmp==inf) printf("oo
");else printf("%d
",tmp);
return 0;
}