题目链接:
题目大意:
给平面上 N N 个点,问是否存在两条直线(可重合)使得每个点至少在某一条直线上?
数据范围:
1≤N≤105|xi|,|yi|≤109 1 ≤ N ≤ 10 5 | x i | , | y i | ≤ 10 9
解题思路:
任选
3
3
个点,在其中选 个点,使之为一条直线,把在这条直线上的点删掉,然后判断其余的点是否在另一条直线上。(叉积判共线)
AC代码:
/********************************************
*Author* :XzzF
*Created Time* : 2018年04月06日 星期五 16时27分02秒
* Ended Time* : 2018年04月06日 星期五 16时57分14秒
*********************************************/
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf = 1 << 30;
const LL INF = 1LL << 60;
const int MaxN = 100005;
int n;
bool used[MaxN + 5];
struct Point {
LL x, y;
Point () {}
Point (LL _x, LL _y) {
x = _x; y = _y;
}
friend Point operator - (const Point A, const Point B){
return Point (A.x - B.x, A.y - B.y);
}
}PP[MaxN + 5];
typedef Point Vector;
LL Cross(Point A, Point B) {
return A.x * B.y - A.y * B.x;
}
bool check() {
int Na = -1, Nb = -1;
for(int i = 1; i <= n; i++) {
if(used[i]) continue;
if(Na == -1) Na = i;
else if(Nb == -1) Nb = i;
}
if(Na == -1 || Nb == -1) return true;
for(int i = 1; i <= n; i++) {
if(used[i]) continue;
if(Cross(PP[Nb] - PP[Na], PP[i] - PP[Na]) != 0)
return false;
}
return true;
}
bool judge (Point A, Point B) {
memset(used, 0, sizeof(used));
for(int i = 1; i <= n; i++) {
if(Cross(B - A, PP[i] - A) == 0)
used[i] = true;
}
return check();
}
bool solve() {
if(n <= 3) return true;
if(judge(PP[1], PP[2]) || judge(PP[1], PP[3]) || judge(PP[2], PP[3]))
return true;
return false;
}
int main()
{
while(scanf("%d", &n) != EOF)
{
for(int i = 1; i <= n; i++)
scanf("%lld %lld", &PP[i].x, &PP[i].y);
if(solve() ) printf("YES\n");
else printf("NO\n");
}
return 0;
}
赛后听到大佬们随机过的!(Orz) 嗯???还有这种骚操作?
果断学习一下!
主要就是随机两个点,删除在这条直线上的点,再判断其余的点是否在一条直线上。
似乎有种似曾相识的感觉?
随机代码:
/**********************************************
*Author* :XzzF
*Created Time* : 2018/4/11 10:37:54
*Ended Time* : 2018/4/11 10:47:34
*********************************************/
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <ctime>
using namespace std;
typedef long long LL;
const int inf = 1 << 30;
const LL INF = 1LL << 60;
const int MaxN = 100005;
int n;
bool used[MaxN + 5];
struct Point {
LL x, y;
Point () {}
Point (LL _x, LL _y) {
x = _x; y = _y;
}
friend Point operator - (const Point A, const Point B){
return Point (A.x - B.x, A.y - B.y);
}
}PP[MaxN + 5];
typedef Point Vector;
LL Cross(Point A, Point B) {
return A.x * B.y - A.y * B.x;
}
bool check() {
int Na = -1, Nb = -1;
for(int i = 1; i <= n; i++) {
if(used[i]) continue;
if(Na == -1) Na = i;
else if(Nb == -1) Nb = i;
}
if(Na == -1 || Nb == -1) return true;
for(int i = 1; i <= n; i++) {
if(used[i]) continue;
if(Cross(PP[Nb] - PP[Na], PP[i] - PP[Na]) != 0)
return false;
}
return true;
}
bool judge (Point A, Point B) {
memset(used, 0, sizeof(used));
for(int i = 1; i <= n; i++) {
if(Cross(B - A, PP[i] - A) == 0)
used[i] = true;
}
return check();
}
bool solve(Point A, Point B) {
if(n <= 3) return true;
if(judge(A, B) )
return true;
return false;
}
int main()
{
srand(time(NULL));
while(scanf("%d", &n) != EOF)
{
for(int i = 1; i <= n; i++)
scanf("%lld %lld", &PP[i].x, &PP[i].y);
bool f = 0;
if(n <= 3) f = 1;
else {
for(int i = 1; i <= 200; i++) {
int a = rand() % n + 1;
int b = rand() % n + 1;
while(a == b) b = rand() % n + 1;
if(solve(PP[a], PP[b])) {
f = 1;
break;
}
}
}
if(f) printf("YES\n");
else printf("NO\n");
}
return 0;
}