UVA10256 The Great Divide
考虑对两个点集求出凸包,显然如果这两个凸包相离就合法,然后问题就转化成了这两个凸包是否有交。
设红点凸包包围的点集为 ,蓝点凸包包围的点集为 ,问题为询问是否 ,即 。
于是对所有蓝点取反,求出新的蓝点凸包,再与红点凸包计算它们闵可夫斯基和的凸包,如果 在它的内部(包含边界),就说明 和 有交,输出 No
;否则输出 Yes
。
时间复杂度 ,瓶颈在于对点排序。
code
const int maxn = 510; int n, m, stk[maxn], top; struct node { int x, y; node(int a = 0, int b = 0) : x(a), y(b) {} }; node operator + (node a, node b) { return node(a.x + b.x, a.y + b.y); } node operator - (node a, node b) { return node(a.x - b.x, a.y - b.y); } int operator * (node a, node b) { return a.x * b.y - a.y * b.x; } bool cmp(node a, node b) { return a.x < b.x || (a.x == b.x && a.y < b.y); } vector<node> convex(vector<node> vc) { sort(vc.begin(), vc.end(), cmp); top = 0; int n = (int)vc.size(); if (n == 1) { return vc; } for (int i = 0; i < n; ++i) { while (top >= 2 && (vc[stk[top]] - vc[stk[top - 1]]) * (vc[i] - vc[stk[top - 1]]) <= 0) { --top; } stk[++top] = i; } vector<node> res; for (int i = 1; i < top; ++i) { res.pb(vc[stk[i]]); } top = 0; for (int i = n - 1; ~i; --i) { while (top >= 2 && (vc[stk[top]] - vc[stk[top - 1]]) * (vc[i] - vc[stk[top - 1]]) <= 0) { --top; } stk[++top] = i; } for (int i = 1; i < top; ++i) { res.pb(vc[stk[i]]); } return res; } vector<node> mkfsj(vector<node> a, vector<node> b) { int n = (int)a.size(), m = (int)b.size(); vector<node> va(n), vb(m), res; res.pb(a[0] + b[0]); for (int i = 0; i < n; ++i) { va[i] = a[(i + 1) % n] - a[i]; } for (int i = 0; i < m; ++i) { vb[i] = b[(i + 1) % m] - b[i]; } int i = 0, j = 0; while (i < n && j < m) { res.pb(res.back() + (va[i] * vb[j] >= 0 ? va[i++] : vb[j++])); } while (i < n) { res.pb(res.back() + va[i++]); } while (j < m) { res.pb(res.back() + vb[j++]); } res.erase(res.begin()); return res; } bool check(vector<node> a, vector<node> b) { vector<node> res = mkfsj(a, b); node O; int n = (int)res.size(); for (int i = 1; i < n; ++i) { if ((O - res[i - 1]) * (res[i] - res[i - 1]) > 0) { return 0; } } return 1; } void solve() { vector<node> a, b; for (int i = 0, x, y; i < n; ++i) { scanf("%d%d", &x, &y); a.pb(node(x, y)); } for (int i = 0, x, y; i < m; ++i) { scanf("%d%d", &x, &y); b.pb(node(-x, -y)); } vector<node> v1 = convex(a), v2 = convex(b); puts(check(v1, v2) ? "No" : "Yes"); } int main() { while (scanf("%d%d", &n, &m) == 2 && n) { solve(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!