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\n", 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\n" , 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 ¢er, 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\n", 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
转载于:https://www.cnblogs.com/xysmlx/p/3870091.html
ZOJ 3720 Magnet Darts (计算几何,概率,判点是否在多边形内)相关推荐
- 用概率判生死:法庭上的数学证据
给大家分享一个概率统计的故事. 法官如果通过掷硬币的方式来判一个人有没有罪,肯定没人会服.但历史上真的发生过这种事,当然不会是抛硬币,而是--算一个更复杂的概率.概率断案好不好用,看看几个案例就知道了 ...
- zoj 2709 Lottery 组合数,概率,贪心 (8-F)
题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2709 题解: 1 组合数的计算,用DP,速度又快又简洁. ...
- ZOJ 1696 Viva Confetti 计算几何
计算几何:按顺序给n个圆覆盖.问最后能够有几个圆被看见.. . 对每一个圆求和其它圆的交点,每两个交点之间就是可能被看到的圆弧,取圆弧的中点,往外扩展一点或者往里缩一点,从上往下推断有没有圆能够盖住这 ...
- ZOJ 2675 Little Mammoth(计算几何)
圆形与矩形截面的面积 三角仍然可以做到这一点 代码: #include<stdio.h> #include<string.h> #include<stdlib.h> ...
- ZOJ 3502 Contest 状态压缩 概率 DP
链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3502 1 #include <iostream> 2 # ...
- 计算几何之用叉乘求多边形面积
一.理论基础 二维向量叉乘得到的是对应平行四边形的有向面积,所以,只要保证按照逆时针对点排序,以下的算法都是可行的: ①凸多边形,选取一个A0,从A1开始依次挑选相邻的两个点,求三角形面积,求和即可 ...
- h5 页面判段是否是微信内,是否是IOS,区分qq内置浏览器和QQ浏览器
/*** 判断当前的环境是否在 微信环境下* */isWeiXin: () => {var ua = window.navigator.userAgent.toLowerCase();if (u ...
- 二维几何基础大合集!《计算几何全家桶(一)》(基础运算、点、线、多边形、圆、网格)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的模板整合计划 目录 1.基本运算 1.1 判断正负函数(sgn) 1.2 点积(数量积.内积)(Dot) 1.3 向量积 ...
- 计算几何与图形学有关的几种常用算法(二)
原文地址:http://blog.csdn.net/orbit/article/details/7101869 3.6 用矢量的叉积判断直线段是否有交 矢量叉积计算的另一个常用用途是直线段求交.求交算 ...
最新文章
- char[]数组与char *指针的区别
- linux挂载硬盘 只读,mount: /dev/vdb 写保护,将以只读方式挂载
- 实验详解——parted单磁盘分区并进行配额
- Linux基本命令之pidof和kill/killall
- ASP.NET 实现PDF文件下载[转]
- 5 月数据库排行:PgSQL 慢增长,MySQL冲击第一!
- typescript 爬坑速记
- html实现下载功能(两种方式)
- 淘宝新手开店可掌握的爆款核心思路
- 移动广告平台盈利模式
- 建筑智能化资质办理要求
- 费曼 计算机科学 讲义,《费曼物理讲义》3 物理学与其他科学的关系
- 下一代5G网络:比4G快1000倍 普及至少需8年
- 【机器学习】笔记1:回归与误差分析
- 切换cuda版本之后/usr/local/cuda/lib64找不到的问题
- AutoCAD Civil 3D-创建道路模型(2 道路的挖填方量计算及条件部件)
- 计时器工具 StopWatch
- WebRTC之Jitsi-meet实现语音转文字
- 中点和中值滤波的区别_P8:滤波器(Filter)
- 混合模型:基于VGG-16+PCA+Meanshift/DBSCAN的图像分类(附代码数据集)