《TOJ 2925》
Accept :(题目就是这个..)
思路:一开始读错题来着。以为两条线不能有一样的点。
后面发现题目就是让我们求两条线,每条线只经过两个点即可。
首先,考虑如何判断一条直线经过两个点:
枚举一个点,然后可以发现,对于在同一条直线上的点,他们肯定都会经过这个枚举的点,并且因为在同一条直线上,所以斜率相同。
所以可以map计算同斜率的点的个数。
函数封装部分操作来减少码量。
然后以另一个点为起点,来寻找。最后判断是否有垂直即可。
注意的是,这里的点可能存在重复,而且重复的点我们要看做不同的点。所以可能存在xx == 0 && yy == 0的情况。
Code:
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e3+5; const int M = 250005; const LL Mod = 1e9+7; #define pi acos(-1) #define INF 1e8 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline LL read() { LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void cal(int &xx,int &yy) { int ma = __gcd(xx,yy); xx /= ma,yy /= ma; if(xx*yy < 0) xx = -abs(xx),yy = abs(yy); } int n,x[105],y[105]; bool slove() { int f = 0; for(int i = 1;i <= n;++i) { map<pii,int> mp; int cnt1 = 0,cnt2 = 0; for(int j = 1;j <= n;++j)//统计斜率情况 { if(i == j) continue; int xx = x[i]-x[j],yy = y[i]-y[j]; if(xx == 0 || yy == 0) { if(xx == 0) cnt1++; if(yy == 0) cnt2++; } else cal(xx,yy),mp[pii{xx,yy}]++; } for(int j = 1;j <= n;++j) { map<pii,int> qm; if(j == i || f) continue; int num1 = 0,num2 = 0; for(int k = 1;k <= n;++k) { if(j == k || f) continue; int px = x[j]-x[k],py = y[j]-y[k]; if(px == 0 || py == 0) { if(px == 0) num1++; if(py == 0) num2++; } else cal(px,py),qm[pii{px,py}]++; } if(cnt1 == 1 && num2 == 1) f = 1; if(cnt2 == 1 && num1 == 1) f = 1; for(int k = 1;k <= n;++k) { if(j == k) continue; int px = x[j]-x[k],py = y[j]-y[k]; if(px == 0 || py == 0) continue; cal(px,py); int tx = py,ty = px; tx = -tx; cal(tx,ty); if(qm[pii(px,py)] == 1 && mp[pii(tx,ty)] == 1) { // printf("px is %d py is %d tx is %d ty is %d\n",px,py,tx,ty); f = 1; } } } } if(f) return true; return false; } int main() { while(~scanf("%d",&n)) { for(int i = 1;i <= n;++i) x[i] = read(),y[i] = read(); printf("%s\n",slove() ? "YES" : "NO"); } return 0; }