ZOJ3720 Magnet Darts(点在多边形内)

题目链接: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.

Input

There are multiple test cases. For each test case:

The first line contains four real numbers P0Q0P1Q1 (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), AB (-100≤AB≤100). The meaning of them is in the description above.

Next N lines, each line contains two intergers XiYi, 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[n]=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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值