Codeforces Round #291 (Div. 2) -- B. Han Solo and Lazer Gun (计算几何~暴力)

本文探讨了在战斗场上,使用最新双管激光枪击溃众多帝国士兵的最有效方式。通过数学分析和几何理解,文章揭示了如何仅用最少的射击次数实现目标。详细介绍了输入参数的含义、解决方案的步骤以及实例解析。

B. Han Solo and Lazer Gun
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

There are n Imperial stormtroopers on the field. The battle field is a plane with Cartesian coordinate system. Each stormtrooper is associated with his coordinates (x, y) on this plane.

Han Solo has the newest duplex lazer gun to fight these stormtroopers. It is situated at the point (x0, y0). In one shot it can can destroy all the stormtroopers, situated on some line that crosses point (x0, y0).

Your task is to determine what minimum number of shots Han Solo needs to defeat all the stormtroopers.

The gun is the newest invention, it shoots very quickly and even after a very large number of shots the stormtroopers don't have enough time to realize what's happening and change their location.

Input

The first line contains three integers nx0 и y0 (1 ≤ n ≤ 1000 - 104 ≤ x0, y0 ≤ 104) — the number of stormtroopers on the battle field and the coordinates of your gun.

Next n lines contain two integers each xiyi ( - 104 ≤ xi, yi ≤ 104) — the coordinates of the stormtroopers on the battlefield. It is guaranteed that no stormtrooper stands at the same point with the gun. Multiple stormtroopers can stand at the same point.

Output

Print a single integer — the minimum number of shots Han Solo needs to destroy all the stormtroopers.

Sample test(s)
input
4 0 0
1 1
2 2
2 0
-1 -1
output
2
input
2 1 2
1 1
1 0
output
1
Note

Explanation to the first and second samples from the statement, respectively:







思路:刚开始我用的向量做得,一个一个暴力算出角度,看向量是否平行,平行的话就不要ans++,然后,,就这样WA了╮(╯_╰)╭,其实最好不要用向量做,因为存在浮点数误差,算着算着不知名的错误就来了,除了直接算角度,还可以用求最大公约数来求同一直线上的点(用一个点代表直线上的点,因为都是整数,所以如果在同一直线上就会有公共向量,都除以其最大公约数就可以求得公共向量,还有在x,y轴上的公共向量可以用(1,0)(0,1)表示。。公共向量可以用set存储)


AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;

int gcd(int a, int b) {		//求最大公约数 
	if(a > b) return gcd(b, a);
	if(b % a == 0) return a;
	return gcd(b % a, a);
}

int main() {
	int n, x, y;
	set<pair<int, int> > a;
	while(scanf("%d %d %d", &n, &x, &y) != EOF) {
		for(int i = 0; i < n; i++) {
			int p, q;
			scanf("%d %d", &p, &q);
			p -= x, q -= y;
			if(p == 0) a.insert(make_pair(0, 1));
			else if(q == 0) a.insert(make_pair(1, 0));
			else 
			{
				int t = gcd(abs(p), abs(q));
				p /= t;
				q /= t;
				if(p < 0) { p = -p; q = -q; }
				a.insert(make_pair(p, q));
			}
		}
		printf("%d\n", a.size());
	}
	return 0;
} 








最开始套模板做得,,╮(╯▽╰)╭


贴一下蛋疼的代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

const double PI = 4 * atan(1.0);

struct Point {
	double x, y;
	Point(double x = 0, double y = 0) : x(x) , y(y) { }  
};

typedef Point Vector;  

Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
Vector operator - (Vector A, Vector B) { return Vector(A.x-B.x, A.y-B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } 

bool operator < (const Point& a, const Point& b) {
	return a.x < b.x || (a.x == b.x && a.y < b.y);
} 

const double eps = 1e-9;
int dcmp(double x) {
	if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
}

bool operator == (const Point& a, const Point& b) {
	return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; } 
double Length(Vector A) { return sqrt(Dot(A, A)); }		
double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); } 

double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
double Area2(Point A, Point B, Point C) { return Cross(B-A, C-A); }

Vector Rotate(Vector A, double rad) {
	return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad) );
} 

Vector Normal(Vector A) {  
    double L = Length(A);  
    return Vector(-A.y/L, A.x/L);  
}

Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) {
	Vector u = P - Q;
	double t = Cross(w, u) / Cross(v, w);
	return P + v * t;
} 
 
double DistanceToLine(Point P, Point A, Point B) {  
    Vector v1 = B-A, v2 = P - A;  
    return fabs(Cross(v1,v2) / Length(v1)); 
}  

double DistanceToSegment(Point P, Point A, Point B) {  
    if(A==B) return Length(P-A);  
    Vector v1 = B - A, v2 = P - A, v3 = P - B;  
    if(dcmp(Dot(v1, v2)) < 0) return Length(v2);  
    else if(dcmp(Dot(v1, v3)) > 0) return Length(v3);  
    else return fabs(Cross(v1, v2)) / Length(v1);  
}  

Point GetLineProjection(Point P, Point A, Point B) {
	Vector v = B - A;
	return A + v * ( Dot(v, P-A) / Dot(v, v) ); 
}  

bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) {
	double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
			c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
	return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
} 

bool OnSegment(Point p, Point a1, Point a2) {
	return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) < 0;
} 

double ConvexPolygonArea(Point* p, int n) {  
    double area = 0;  
    for(int i = 1; i < n-1; i++)  
        area += Cross(p[i] - p[0], p[i + 1] - p[0]);  
    return area / 2;  
}  

int main() {
	Point A, B[1005];
	Vector V[1005];
	int n;
	while(scanf("%d %lf %lf", &n, &A.x, &A.y) != EOF) {
		for(int i = 0; i < n; i++) {
			scanf("%lf %lf", &B[i].x, &B[i].y);
			V[i] = B[i] - A;
		}
		
		int ans = n, i, j;
		for(i = 1; i < n; i++) { 
			for(j = 0; j < i; j++) {
				if( fabs(fabs(Angle(V[i], V[j]) ) - PI) < eps || fabs(fabs(Angle(V[i], V[j])) - 0) < eps)
				{ ans--; break; }
			}
		}
		printf("%d\n", ans);
	}
	return 0;
} 






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值