向量基本运算
点积
叉积
一.Transmitters
由叉积的基本定理得出,要判断一个点c再一条直线ab的左边还是右边,只要看(b-a)*(c-a)大于0还是小于0,对于这题,我们可以将左右边看成发射范围的半圆,因为要找出覆盖最多点的数量,所以最优解肯定有一个点再直径上,再通过叉积找出所有在这个点左侧的点。并且在初始化的时候,如果发现一个点到圆心的距离大于圆的半径,那这个点就不用考虑了。
点击查看代码
#include <iostream> // 输入输出流
#include <iomanip> // 输入输出格式控制
#include <fstream> // 文件输入输出流
#include <sstream> // 字符串输入输出流
#include <cmath> // 数学函数
#include <string> // 字符串操作
#include <vector> // 动态数组容器
#include <queue> // 队列容器
#include <stack> // 栈容器
#include <set> // 集合容器
#include <map> // 映射容器
#include <algorithm> // 算法
#include <bitset> // 位集容器
#include <stdio.h> // 标准输入输出
using namespace std;
#define int long long
const int N = 1e6 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
double a[N], b[N];
double x, y, r;
double dis(double xx, double yy) // 计算距离
{return sqrt(1.0 * (x - xx) * (x - xx) + (y - yy) * (y - yy));
}
double cha(double xx, double yy, double xxx, double yyy) // 计算叉积
{return (xx - x) * (yyy - y) - (xxx - x) * (yy - y);
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);while (cin >> x >> y >> r, r >= 0){int n;cin >> n;int cnt = 0;for (int i = 1; i <= n; i++){int xx, yy;cin >> xx >> yy;if (dis(xx, yy) <= r) // 将点到圆心距离小于r的点放入{a[++cnt] = xx;b[cnt] = yy;}}int max1 = 0;for (int i = 1; i <= cnt; i++) // 枚举每一个点在半圆的直径上,计算其左侧的点{int s = 0;for (int j = 1; j <= cnt; j++){if (cha(a[i], b[i], a[j], b[j]) >= 0) // 如果叉积大于0,说明在左侧,等于0,则在直径上,都符合条件{s++;}}max1 = max(max1, s); // 记录最大的左侧点数}cout << max1 << "\n";}return 0;
}
将一个纸板分成了n+1个部分,因为每个分割点的坐标x是递减的,所以可以想到二分,而每个部分则是由分割线右边的那块地方包含的,所以要判断每个点落在哪个部分,就是不断二分判断对于那个部分,点和分割线的叉积是否小于0。
点击查看代码
#include <iostream> // 输入输出流
#include <iomanip> // 输入输出格式控制
#include <fstream> // 文件输入输出流
#include <sstream> // 字符串输入输出流
#include <cmath> // 数学函数
#include <string> // 字符串操作
#include <vector> // 动态数组容器
#include <queue> // 队列容器
#include <stack> // 栈容器
#include <set> // 集合容器
#include <map> // 映射容器
#include <algorithm> // 算法
#include <bitset> // 位集容器
#include <stdio.h> // 标准输入输出
#include <cstring>
using namespace std;
const int N = 100010, M = 20;
#define int long long
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
int x, y, n, m, x1, y3;
struct vv
{int x, y;
} a[N], b[N], p;
int cha(int mid)
{return ((a[mid].x - b[mid].x) * (p.y - b[mid].y)) - (a[mid].y - b[mid].y) * (p.x - b[mid].x);
}
int s[N];
int find() // 二分查找对于每个部分的叉积是否小于0
{int l = 1, r = n + 1;while (l <= r){int mid = (l + r + 1) / 2;if (cha(mid) <= 0){l = mid + 1;}else{r = mid - 1;}}return r;
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);while (cin >> n, n){cin >> m >> x >> y >> x1 >> y3;int cnt = 1;a[1].x = x, a[1].y = y, b[1].x = x, b[1].y = y3; // 先将盒子的起点的两端点记录数组for (int i = 2; i <= n + 1; i++){int l, r;cin >> l >> r;a[i].x = l;a[i].y = y;b[i].x = r;b[i].y = y3;}memset(s, 0, sizeof(s));while (m--) // 对于每个玩具,find找出其所在的部分,然后加1,找出最大值。{cin >> p.x >> p.y;s[find()]++;}for (int i = 1; i <= n + 1; i++){cout << i - 1 << ": " << s[i] << endl;}cout << "\n";}return 0;
}