ZOJ3720 Magnet Darts(点在多边形内)
2014-03-31 20:29
155 查看
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5043
Magnet Darts
Time Limit: 2 Seconds Memory Limit: 65536 KB
There is a magnet board on the wall, and you can throw magnet darts towards it. When a magnet dart hit a point (x, y), because of the magnetism, it will be pulled to the nearest integer
point (x', y'), and you can get a score of Ax' + By'.
To make the game more interesting, only the integer points in the given N-polygon (or on the border) could get score. And we assume all the throw must hit a point which is
in a rectangle area, and the polygon is also in the rectangle. Your task is to calculate the average expectation of score per throw.
The first line contains four real numbers P0, Q0, P1, Q1 (0≤P0<P1≤500,
0≤Q0<Q1≤500), represents the lower left point and the upper right point of the rectangle area, all the throw must hit a point in it.
The second line contains three integers N (3≤N≤20), A, B (-100≤A, B≤100). The meaning of them is in the description above.
Next N lines, each line contains two intergers Xi, Yi, represents the ith vertex of the polygon by clockwise order, we
promise each vertex is in the rectangle area.
There is a blank line between every two cases.
题意:向一个矩形的靶子上扔飞镖,扔的飞镖会自动移动到距离它最近的整数点上。如果整数点在多边形A内,则能得到A*i+B*j分,求平均每一镖得分的数学期望。
首先要理解,什么叫做移动到最近的整数点上。画图可以发现,对于一个整数点,落在它左0.5,右0.5,上0.5,下0.5组成的正方形区域内的飞镖会被吸引到这个点上来。
由此我们可以推出,靶子上能得分的区域,就是在多边形A内的所有整数点所组成的正方形的面积之和。
得分的概率为正方形面积之和/矩形面积;得的分数期望为对于所有A中的整数点,(A*i+B*j)*该点的正方形面积的和。
所以最终的数学期望为所有A中的整数点,(A*i+B*j)*该点的正方形面积的和/矩形面积。
注意点1:A不一定是凸多边形,所以要用转角法判断点是否在多边形内(关于转角法,代码来自大白书,在下小沙包一只,就不乱解释了)。
注意点2:整点的正方形面积有可能会超出矩形边界,要注意此时它的形状不再是正方形了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
using namespace std;
#define eps 1e-8
struct point
{
double x,y;
point(){}
point(double _x,double _y)
{
x=_x;y=_y;
}
point operator - (const point &b) const
{
return point(x-b.x,y-b.y);
}
}pa[50],p,q;
int n,a,b;
int dcmp(double x)
{
return (x>eps)-(x<-eps);
}
double cross(point a,point b)
{
return a.x*b.y-b.x*a.y;
}
double dot(point a,point b)
{
return a.x*b.x+a.y*b.y;
}
bool onseg(point p,point a1,point a2)//判断点是否在线段a1,a2上
{
return dcmp(cross(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<=0;
}
int inpolygon(point p)//判断点是否在多边形内部
{
int wn=0;
for (int i=0;i<n;i++)
{
if (onseg(p,pa[i],pa[i+1])==1) return 1;
int k=dcmp(cross(pa[i+1]-pa[i],p-pa[i]));
int d1=dcmp(pa[i].y-p.y);
int d2=dcmp(pa[i+1].y-p.y);
if (k>0&&d1<=0&&d2>0) ++wn;
if (k<0&&d2<=0&&d1>0) --wn;
}
if (wn!=0) return 1;
return 0;
}
int main()
{
while (scanf("%lf%lf%lf%lf",&p.x,&p.y,&q.x,&q.y)!=EOF)
{
scanf("%d%d%d",&n,&a,&b);
for (int i=0;i<n;i++)
{
scanf("%lf%lf",&pa[i].x,&pa[i].y);
}
pa
=pa[0];
double ans=0.0;
for (int i=ceil(p.x);i<=(int)q.x;i++)
{
for (int j=ceil(p.y);j<=(int)q.y;j++)
{
if (inpolygon(point(i,j))==0) continue;
double up,down,left,right;//计算出吸引到该点的范围
up=min(j+0.5,q.y);
down=max(j-0.5,p.y);
left=max(i-0.5,p.x);
right=min(i+0.5,q.x);
double area=(up-down)*(right-left);
ans=ans+area*(a*i+b*j);//计算得分概率
}
}
ans=ans/((q.x-p.x)*(q.y-p.y));//除以总面积即为答案
printf("%.3lf\n",ans);
}
return 0;
}
Magnet Darts
Time Limit: 2 Seconds Memory Limit: 65536 KB
There is a magnet board on the wall, and you can throw magnet darts towards it. When a magnet dart hit a point (x, y), because of the magnetism, it will be pulled to the nearest integer
point (x', y'), and you can get a score of Ax' + By'.
To make the game more interesting, only the integer points in the given N-polygon (or on the border) could get score. And we assume all the throw must hit a point which is
in a rectangle area, and the polygon is also in the rectangle. Your task is to calculate the average expectation of score per throw.
Input
There are multiple test cases. For each test case:The first line contains four real numbers P0, Q0, P1, Q1 (0≤P0<P1≤500,
0≤Q0<Q1≤500), represents the lower left point and the upper right point of the rectangle area, all the throw must hit a point in it.
The second line contains three integers N (3≤N≤20), A, B (-100≤A, B≤100). The meaning of them is in the description above.
Next N lines, each line contains two intergers Xi, Yi, represents the ith vertex of the polygon by clockwise order, we
promise each vertex is in the rectangle area.
There is a blank line between every two cases.
Output
One line for each case. The the average expectation of score per throw with three decimal places.Sample Input
0 0 4 3 3 1 1 2 3 4 2 3 0
Sample Output
1.333
题意:向一个矩形的靶子上扔飞镖,扔的飞镖会自动移动到距离它最近的整数点上。如果整数点在多边形A内,则能得到A*i+B*j分,求平均每一镖得分的数学期望。
首先要理解,什么叫做移动到最近的整数点上。画图可以发现,对于一个整数点,落在它左0.5,右0.5,上0.5,下0.5组成的正方形区域内的飞镖会被吸引到这个点上来。
由此我们可以推出,靶子上能得分的区域,就是在多边形A内的所有整数点所组成的正方形的面积之和。
得分的概率为正方形面积之和/矩形面积;得的分数期望为对于所有A中的整数点,(A*i+B*j)*该点的正方形面积的和。
所以最终的数学期望为所有A中的整数点,(A*i+B*j)*该点的正方形面积的和/矩形面积。
注意点1:A不一定是凸多边形,所以要用转角法判断点是否在多边形内(关于转角法,代码来自大白书,在下小沙包一只,就不乱解释了)。
注意点2:整点的正方形面积有可能会超出矩形边界,要注意此时它的形状不再是正方形了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
using namespace std;
#define eps 1e-8
struct point
{
double x,y;
point(){}
point(double _x,double _y)
{
x=_x;y=_y;
}
point operator - (const point &b) const
{
return point(x-b.x,y-b.y);
}
}pa[50],p,q;
int n,a,b;
int dcmp(double x)
{
return (x>eps)-(x<-eps);
}
double cross(point a,point b)
{
return a.x*b.y-b.x*a.y;
}
double dot(point a,point b)
{
return a.x*b.x+a.y*b.y;
}
bool onseg(point p,point a1,point a2)//判断点是否在线段a1,a2上
{
return dcmp(cross(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<=0;
}
int inpolygon(point p)//判断点是否在多边形内部
{
int wn=0;
for (int i=0;i<n;i++)
{
if (onseg(p,pa[i],pa[i+1])==1) return 1;
int k=dcmp(cross(pa[i+1]-pa[i],p-pa[i]));
int d1=dcmp(pa[i].y-p.y);
int d2=dcmp(pa[i+1].y-p.y);
if (k>0&&d1<=0&&d2>0) ++wn;
if (k<0&&d2<=0&&d1>0) --wn;
}
if (wn!=0) return 1;
return 0;
}
int main()
{
while (scanf("%lf%lf%lf%lf",&p.x,&p.y,&q.x,&q.y)!=EOF)
{
scanf("%d%d%d",&n,&a,&b);
for (int i=0;i<n;i++)
{
scanf("%lf%lf",&pa[i].x,&pa[i].y);
}
pa
=pa[0];
double ans=0.0;
for (int i=ceil(p.x);i<=(int)q.x;i++)
{
for (int j=ceil(p.y);j<=(int)q.y;j++)
{
if (inpolygon(point(i,j))==0) continue;
double up,down,left,right;//计算出吸引到该点的范围
up=min(j+0.5,q.y);
down=max(j-0.5,p.y);
left=max(i-0.5,p.x);
right=min(i+0.5,q.x);
double area=(up-down)*(right-left);
ans=ans+area*(a*i+b*j);//计算得分概率
}
}
ans=ans/((q.x-p.x)*(q.y-p.y));//除以总面积即为答案
printf("%.3lf\n",ans);
}
return 0;
}
相关文章推荐
- ZOJ3720 Magnet Darts(点在多边形内)
- ZOJ 3720 Magnet Darts (计算几何,概率,判点是否在多边形内)
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- ZOJ 3720 Magnet Darts(几何)
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- Codeforces Beta Round #83 (Div. 1 Only) E.Darts 凸多边形面积交
- CSDN上的各位高手,有谁做过关于多边形的Voronoi图的求解算法啊
- SIMD-BT 模型下的并行求点在多边形中
- 判断一个点是否在多边形内部
- [arcengine+geoProcessor]相交多边形的算法分析过程与实现