zoukankan      html  css  js  c++  java
  • [POJ2318]TOYS (计算几何 行列式(叉乘)+二分)

    题目链接:http://poj.org/problem?id=2318

    题意大致是给了m个玩具,这m个玩具在n+1个盒子里。坐标给定,求每个盒子里有多少个玩具。

    简单考虑就是判断点在线段的哪一侧,二分+判断即可。

    方法1:在BJTU集训队课件上看到的:

    检查线段p1p3是在线段p1p2的顺时针方向还是逆时针方向
    计算(p3–p1)x(p2–p1)

    方法2:学堂在线上邓俊辉老师开的计算几何课程讲了一个用行列式的方法,具体证明可以参考计算几何这门课程。

    判断p2点在直线p1p3的左侧还是右侧:
    |p1.x p1.y 1|
    |p3.x p3.y 1|
    |p2.x p2.y 1|

    泛型在调用的时候特别麻烦,回头改成用宏替换好了。代码如下:

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <iomanip>
      4 #include <cstring>
      5 #include <climits>
      6 #include <complex>
      7 #include <fstream>
      8 #include <cassert>
      9 #include <cstdio>
     10 #include <bitset>
     11 #include <vector>
     12 #include <deque>
     13 #include <queue>
     14 #include <stack>
     15 #include <ctime>
     16 #include <set>
     17 #include <map>
     18 #include <cmath>
     19 
     20 using namespace std;
     21 
     22 template<typename pp>
     23 struct Point {
     24     pp x;
     25     pp y;
     26     Point(){}
     27     Point(pp xx, pp yy) : x(xx), y(yy) {}
     28 };
     29 
     30 
     31 template<typename pp>
     32 struct Line {
     33     Point<pp> u;
     34     Point<pp> v;
     35     Line() {}
     36     Line(Point<pp> uu, Point<pp> vv) : u(uu), v(vv) {}
     37 };
     38 
     39 /*
     40 检查线段p1p3是在线段p1p2的顺时针方向还是逆时针方向
     41 计算(p3–p1)x(p2–p1)
     42 */
     43 template<typename pp>
     44 pp direction1(Point<pp> p1, Point<pp> p2, Point<pp> p3) { // >0右拐 <0左拐
     45     return (p3.x-p1.x)*(p2.y-p1.y)-(p2.x-p1.x)*(p3.y-p1.y);
     46 }
     47 
     48 /*
     49 |p1.x p1.y 1|
     50 |p3.x p3.y 1|
     51 |p2.x p2.y 1|
     52 */
     53 template<typename pp>
     54 pp direction2(Point<pp> p1, Point<pp> p2, Point<pp> p3) { // >0右拐 <0左拐
     55     return (p1.x*p3.y+p1.y*p2.x+p3.x*p2.y)-(p2.x*p3.y+p1.x*p2.y+p1.y*p3.x);
     56 }
     57 
     58 
     59 const int maxn = 6666;
     60 int n, m;
     61 int ex1, ey1, ex2, ey2;
     62 Line<int> line[maxn];
     63 int ans[maxn];
     64 
     65 int main() {
     66     // freopen("in", "r", stdin);
     67     int flg = 1;
     68     while(~scanf("%d", &n) && n) {
     69         memset(ans, 0, sizeof(ans));
     70         scanf("%d %d %d %d %d", &m, &ex1, &ey1, &ex2, &ey2);
     71         int Ui, Li;
     72         for(int i = 0; i < n; i++) {
     73             scanf("%d %d", &Ui, &Li);
     74             line[i] = Line<int>(Point<int>(Ui, ey1), Point<int>(Li, ey2));
     75         }
     76         line[n] = Line<int>(Point<int>(ex2, ey1), Point<int>(ex2, ey2));
     77         int x, y;
     78         Point<int> p;
     79         while(m--) {
     80             scanf("%d %d", &x, &y);
     81             p = Point<int>(x, y);
     82             int ll = 0, rr = n;
     83             int tmp;
     84             while(ll <= rr) {
     85                 int mm = (ll + rr) >> 1;
     86                 if(direction1<int>(p, line[mm].u, line[mm].v) > 0) {
     87                     tmp = mm;
     88                     rr = mm - 1;
     89                 }
     90                 else ll = mm + 1;
     91             }
     92             ans[tmp]++;
     93         }
     94         flg ? flg = 0 : printf("
    ");
     95         for(int i = 0; i <= n; i++) {
     96             printf("%d: %d
    ", i, ans[i]);
     97         }
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    机器学习笔记之Boosting算法
    机器学习笔记之多重共线性问题以及如何解决
    机器学习笔记之在Visual Studio Code中使用Jupyter Notebook
    高数学习笔记之范数与距离度量(python实现)
    机器学习笔记之线性回归最小二乘法(公式推导和非调包实现)
    机器学习笔记之线性回归数学推导
    高数笔记之期望、方差与最小二乘法
    DataTable 去重 测试
    vs2019 项目历史记录
    sql 求和 语句
  • 原文地址:https://www.cnblogs.com/kirai/p/5205007.html
Copyright © 2011-2022 走看看