• ZOJ 3720 Magnet Darts (计算几何,概率,判点是否在多边形内)


    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3720

    题意:

    在一个矩形区域投掷飞镖,因此飞镖只会落在整点上,投到每个点的得分是Ax+By。矩形区域里面有个多边形,如果飞镖投在多边形里面则得分,求最终的得分期望。

    即:给定一个矩形内的所有整数点,判断这些点是否在一个多边形内

    方法:

    计算几何的判点是否在多边形内(几何模板),如果在,则令得分加(Ax+By)*以此点为中心边长为1的正方形面积

     1 void solve()
     2 {
     3     double ans = 0;
     4     for (int i = p.x; i <= q.x; i++)
     5     {
     6         for (int j = p.y; j <= q.y; j++)
     7         {
     8             if (PointInPolygon(Point2D(i, j), poly.v, poly.n))
     9                 ans += (a * i + b * j) * (min(i + 0.5, q.x) - max(i - 0.5, p.x)) * (min(j + 0.5, q.y) - max(j - 0.5, p.y));
    10         }
    11     }
    12     printf("%.3f
    ", ans / (q.x - p.x) / (q.y - p.y));
    13 }

    代码:

      1 // #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include <cstdio>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <set>
      8 #include <list>
      9 #include <map>
     10 #include <iterator>
     11 #include <cstdlib>
     12 #include <vector>
     13 #include <queue>
     14 #include <stack>
     15 #include <algorithm>
     16 #include <functional>
     17 using namespace std;
     18 typedef long long LL;
     19 #define ROUND(x) round(x)
     20 #define FLOOR(x) floor(x)
     21 #define CEIL(x) ceil(x)
     22 const int maxn = 0;
     23 const int maxm = 0;
     24 const int inf = 0x3f3f3f3f;
     25 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
     26 // const double INF = 1e30;
     27 // const double eps = 1e-6;
     28 const int P[4] = {0, 0, -1, 1};
     29 const int Q[4] = {1, -1, 0, 0};
     30 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
     31 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
     32 
     33 typedef double db;
     34 const double eps = 1e-7;
     35 const double PI = acos(-1.0);
     36 const double INF = 1e50;
     37 
     38 const int POLYGON_MAX_POINT = 1024;
     39 
     40 db dmin(db a, db b)
     41 {
     42     return a > b ? b : a;
     43 }
     44 db dmax(db a, db b)
     45 {
     46     return a > b ? a : b;
     47 }
     48 int sgn(db a)
     49 {
     50     return a < -eps ? -1 : a > eps;    //返回double型的符号
     51 }
     52 
     53 struct Point2D
     54 {
     55     db x, y;
     56     int id;
     57     Point2D(db _x = 0, db _y = 0): x(_x), y(_y) {}
     58     void input()
     59     {
     60         scanf("%lf%lf" , &x, &y);
     61     }
     62     void output()
     63     {
     64         printf("%.2f %.2f
    " , x, y);
     65     }
     66     //
     67     db len2()
     68     {
     69         return x * x + y * y;
     70     }
     71     //到原点距离
     72     double len()
     73     {
     74         return sqrt(len2());
     75     }
     76     //逆时针转90度
     77     Point2D rotLeft90()
     78     {
     79         return Point2D(-y, x);
     80     }
     81     //顺时针转90度
     82     Point2D rotRight90()
     83     {
     84         return Point2D(y, -x);
     85     }
     86     //绕原点逆时针旋转arc_u
     87     Point2D rot(double arc_u)
     88     {
     89         return Point2D( x * cos(arc_u) - y * sin(arc_u),
     90                         x * sin(arc_u) + y * cos(arc_u) );
     91     }
     92     //绕某点逆时针旋转arc_u
     93     Point2D rotByPoint(Point2D &center, db arc_u)
     94     {
     95         Point2D tmp( x - center.x, y - center.y );
     96         Point2D ans = tmp.rot(arc_u);
     97         ans = ans + center;
     98         return ans;
     99     }
    100 
    101     bool operator == (const Point2D &t) const
    102     {
    103         return sgn(x - t.x) == 0 && sgn(y - t.y) == 0;
    104     }
    105     bool operator < (const Point2D &t) const
    106     {
    107         if ( sgn(x - t.x) == 0 ) return y < t.y;
    108         else return x < t.x;
    109     }
    110     Point2D operator + (const Point2D &t) const
    111     {
    112         return Point2D(x + t.x, y + t.y);
    113     }
    114 
    115     Point2D operator - (const Point2D &t) const
    116     {
    117         return Point2D(x - t.x, y - t.y);
    118     }
    119 
    120     Point2D operator * (const db &t)const
    121     {
    122         return Point2D( t * x, t * y );
    123     }
    124 
    125     Point2D operator / (const db &t) const
    126     {
    127         return Point2D( x / t, y / t );
    128     }
    129     //点乘
    130     db operator ^ (const Point2D &t) const
    131     {
    132         return x * t.x + y * t.y;
    133     }
    134     //叉乘
    135     db operator * (const Point2D &t) const
    136     {
    137         return x * t.y - y * t.x;
    138     }
    139     //两点之间的角度(-PI , PI]
    140     double rotArc(Point2D &t)
    141     {
    142         double perp_product = rotLeft90()^t;
    143         double dot_product = (*this)^t;
    144         if ( sgn(perp_product) == 0 && sgn(dot_product) == -1) return PI;
    145         return sgn(perp_product) * acos( dot_product / len() / t.len() );
    146     }
    147     //标准化
    148     Point2D normalize()
    149     {
    150         return Point2D(x / len(), y / len());
    151     }
    152 };
    153 
    154 struct POLYGON
    155 {
    156     Point2D v[POLYGON_MAX_POINT];
    157     int n;
    158 };
    159 struct Segment2D
    160 {
    161     Point2D s , e;
    162     Segment2D() {}
    163     Segment2D( Point2D _s, Point2D _e ): s(_s), e(_e) {}
    164 };
    165 //0: 点在多边形外
    166 //1: 点在多边形内
    167 bool PonSegment2D(Point2D p, Segment2D seg)
    168 {
    169     return sgn((seg.s - p) * (p - seg.e)) == 0 && sgn((seg.s - p) ^ (p - seg.e)) >= 0;
    170 }
    171 
    172 /**** 判断线段在内部相交***/
    173 bool SegIntersect2D(Segment2D a, Segment2D b)
    174 {
    175     //必须在线段内相交
    176     int d1 = sgn((a.e - a.s) * (b.s - a.s));
    177     int d2 = sgn((a.e - a.s) * (b.e - a.s));
    178     int d3 = sgn((b.e - b.s) * (a.s - b.s));
    179     int d4 = sgn((b.e - b.s) * (a.e - b.s));
    180     if (d1 * d2 < 0 && d3 * d4 < 0) return true;
    181     return false;
    182 }
    183 
    184 int PointInPolygon(Point2D p, Point2D poly[], int n)
    185 {
    186     Segment2D l, seg;
    187     l.s = p;
    188     l.e = p;
    189     l.e.x = INF;//作射线
    190     int i, cnt = 0;
    191     Point2D p1, p2, p3, p4;
    192     for (i = 0; i < n; i++)
    193     {
    194         seg.s = poly[i], seg.e = poly[(i + 1) % n];
    195         if (PonSegment2D(p, seg)) return 2; //点在多边形上
    196         p1 = seg.s, p2 = seg.e , p3 = poly[(i + 2) % n], p4 = poly[(i + 3) % n];
    197         if (SegIntersect2D(l, seg) ||
    198                 PonSegment2D(p2, l) && sgn((p2 - p1) * (p - p1))*sgn((p3 - p2) * (p - p2)) > 0 ||
    199                 PonSegment2D(p2, l) && PonSegment2D(p3, l) &&
    200                 sgn((p2 - p1) * (p - p1))*sgn((p4 - p3) * (p - p3)) > 0 )
    201             cnt++;
    202     }
    203     if (cnt % 2 == 1) return 1; //点在多边形内
    204     return 0;//点在多边形外
    205 }
    206 
    207 POLYGON poly;
    208 Point2D p, q;
    209 db a, b;
    210 void init()
    211 {
    212     //
    213 }
    214 void input()
    215 {
    216     scanf("%d%lf%lf", &poly.n, &a, &b);
    217     for (int i = 0; i < poly.n; i++)
    218     {
    219         scanf("%lf%lf", &poly.v[i].x, &poly.v[i].y);
    220     }
    221 }
    222 void debug()
    223 {
    224     //
    225 }
    226 void solve()
    227 {
    228     double ans = 0;
    229     for (int i = p.x; i <= q.x; i++)
    230     {
    231         for (int j = p.y; j <= q.y; j++)
    232         {
    233             if (PointInPolygon(Point2D(i, j), poly.v, poly.n))
    234                 ans += (a * i + b * j) * (min(i + 0.5, q.x) - max(i - 0.5, p.x)) * (min(j + 0.5, q.y) - max(j - 0.5, p.y));
    235         }
    236     }
    237     printf("%.3f
    ", ans / (q.x - p.x) / (q.y - p.y));
    238 }
    239 void output()
    240 {
    241     //
    242 }
    243 int main()
    244 {
    245     // std::ios_base::sync_with_stdio(false);
    246     // #ifndef ONLINE_JUDGE
    247     //     freopen("in.cpp", "r", stdin);
    248     // #endif
    249 
    250     while (~scanf("%lf%lf%lf%lf", &p.x, &p.y, &q.x, &q.y))
    251     {
    252         init();
    253         input();
    254         solve();
    255         output();
    256     }
    257     return 0;
    258 }
    View Code
  • 相关阅读:
    .Net 控制台动态刷新使用
    VS 将!=转换成 ≠
    C# 自定义Html分页
    .NET MVC ModelBinder基本使用
    C# 重启电脑 程序自启动
    ASP.NET JsonResult返回日期格式及首字母大写解决
    java快速排序代码实现
    系统高可靠的设计需要考虑哪些方面
    sentinel源码学习--transport模块
    TiDB学习笔记分享--存储篇
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3870091.html
Copyright © 2020-2023  润新知