首页 > 代码库 > HDU 4978 A simple probability problem

HDU 4978 A simple probability problem

A simple probability problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 43    Accepted Submission(s): 14



Problem Description
Equally-spaced parallel lines lie on an infinite plane. The separation between adjacent lines is D (D>0). Now considering a circle of diameter D. N points lie on or in the circle. It is guaranteed that any three points are not collinear. Between any two points there‘s a needle. Find the possibility that, if the circle is randomly (with equal probability on any position and direction) thrown onto the same plane described above (with the equally-spaced parallel lines of separation d), at least one needle crosses a line.
 

Input
The first line contains a single integer T (1 <= T <= 100), the number of test cases.

For each set of input data, the first line gives two integers, N and D (N<=100), as described above.You can consider the center of the circle is default as the origin. Lastly N lines is followed, each containing two real numbers that representing the coordinate of a point lying within the circle.
 

Output
Each output should occupy one line. Each line should start with "Case #i: ", followed by a real number round to four decimal places, the probability that at least one needle crosses one line.
 

Sample Input
2 2 2 -0.5 0 0.5 0 3 3 0 1 1 0 -1 0
 

Sample Output
Case #1: 0.3183 Case #2: 0.5123
 

Source
2014 Multi-University Training Contest 10


题目链接  :http://acm.hdu.edu.cn/showproblem.php?pid=4978


题目大意  :一个无限大的平面上有无数条等距平行线,每两条间距为D,给一个直径为D的圆,有n个点分布在圆上或者圆内,点的输入是按照已圆心为原点的坐标系,规定任意三点不共线,任意两点间的线段记为一根针,现在问将该圆投到平面上至少有一根针和其中一条平行线相交的概率


题目分析  :计算几何的问题,首先考虑只有两点的情况即一根针,这就是一个布丰投针问题,公式为P=2L/πD (L为针长,D为平行线间距),再考虑多个点,显然是个凸包问题,如果凸包边上的线可以与平行线相交,凸包内的线必然可以与平行线相交,由投针问题的推广我们可以得到公式P = C/πD (C为凸包周长),详见布丰投针及推广


#include <cstdio>
#include <cstdlib>
#include <cmath>
#define N 200
#define inf 1e-6
#define PI 3.141592653
typedef struct
{
    double x;
    double y;
}point;
point points[N]; 
point chs[N];    
int sp; 

//求凸包周长的模板
double dis(point a, point b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) * 1.0 + (a.y - b.y) * (a.y - b.y));
}


double multi(point p0, point p1, point p2)
{
    return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
int cmp(const void *p, const void *q)
{
     point a = *(point *)p;
     point b = *(point *)q;
    double k = multi(points[0], a, b);
    if(k < -inf)
        return 1;
    else if(fabs(k) < inf && (dis(a, points[0]) - dis(b, points[0])) > inf) 
        return 1;
    else return -1;
}
void convex_hull(int n)
{
    int k, d;
    double miny = points[0].y;
    int index = 0;
    for(int i = 1; i < n; i++) 
    {
        if(points[i].y < miny) 
        {
            miny = points[i].y;
            index = i;
        }
        else if(points[i].y == miny && points[i].x < points[index].x) 
             index = i;
    }
    point temp;
    temp = points[index];
    points[index] = points[0];
    points[0] = temp;
    qsort(points+1, n-1, sizeof(points[0]), cmp);
    chs[0] = points[n-1];
    chs[1] = points[0];
    sp = 1;
    k = 1;
    while(k <= n-1)
    {
        double d = multi(chs[sp], chs[sp-1], points[k]);
        if(d <= 0)
        {
             sp++;
             chs[sp] = points[k];
             k++;
        }
        else sp--;
    }
}
int main()
{
    double sum, d;
    int T, n;
    scanf("%d",&T);
    for(int Ca = 1; Ca <= T; Ca++)
    {
        sum = 0;
        scanf("%d %lf", &n, &d);
        if(n == 0 || n == 1)
        {
            printf("Case #%d: 0.0000\n", Ca);
            continue;
        }
        for(int i = 0; i < n; i++)
            scanf("%lf%lf", &points[i].x, &points[i].y);
        if(n == 2)
        {
            double len = dis(points[0],points[1]);
            printf("Case #%d: %.4f\n", Ca, (2 * len) / (PI * d));
            continue;
        }
        convex_hull(n);
        for(int i = 1; i <= sp; i++) 
            sum += dis(chs[i-1], chs[i]);
        sum += dis(chs[0], chs[sp]);   //算出凸包周长
        printf("Case #%d: %.4f\n", Ca, sum / (PI * d));
    }
}