JZOJ 1077. 【GDKOI2006】防御力量

\(\text{Solution}\)

首先这个题目描述得不清不楚
反正做法是过 \(A\) 城引一条直线,算出直线两侧点数的 \(min\)
找到最优直线,即 \(min\) 最小的
那么重点在判断一个点在直线的哪边
这是二维计算几何的基本操作
好好体会了一番向量积
其几何意义是两向量共定点构成的平行四边形的面积
向量积不满足交换律,其构成的面积顺负逆正
所以考虑 \(Q\) 在直线何处时,取直线上一点 \(Q\)
计算 \(\overrightarrow{PQ} \times \mathbf v\)\(\mathbf v\) 为直线的方向向量(统一向下)
如果值为负,则在直线上方,正为下方,\(0\) 则在直线上

\(\text{Code}\)

#include <cstdio>
#include <iostream>
#define IN inline
#define RE register
using namespace std;

const int N = 10005;
int n;
struct Vector{
	int x, y;
	IN Vector operator - (const Vector &B){return Vector{x - B.x, y - B.y};}
	IN int operator * (const Vector &B){return x * B.y - y * B.x;}
	IN int operator == (const Vector &B){return (x == B.x && y == B.y);}
}p[N], A;

int main()
{
	scanf("%d", &n);
	for(RE int i = 1; i <= n; i++) scanf("%d%d", &p[i].x, &p[i].y);
	scanf("%d%d", &A.x, &A.y);
	int ans = n;
	for(RE int i = 1; i <= n; i++)
	{
		if (p[i] == A) continue;
		int cnt1 = 0, cnt2 = 0;
		for(RE int j = 1; j <= n; j++)
		if (i ^ j)
		{
			int res = (p[i] - A) * (p[j] - A);
			if (res < 0) ++cnt1;
			if (res > 0) ++cnt2;
		}
		ans = min(ans, min(cnt1, cnt2));
	}
	printf("%d\n", ans);
}
原文地址:https://www.cnblogs.com/leiyuanze/p/15823886.html