首页 > 代码库 > [ACM] POJ 3440 Coin Toss (几何概率)

[ACM] POJ 3440 Coin Toss (几何概率)

Coin Toss
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 3019 Accepted: 817

Description

In a popular carnival game, a coin is tossed onto a table with an area that is covered with square tiles in a grid. The prizes are determined by the number of tiles covered by the coin when it comes to rest: the more tiles it covers, the better the prize. In the following diagram, the results from five coin tosses are shown:

In this example:

  • coin 1 covers 1 tile
  • coin 2 covers 2 tiles
  • coin 3 covers 3 tiles
  • coin 4 covers 4 tiles
  • coin 5 covers 2 tiles

Notice that it is acceptable for a coin to land on the boundary of the playing area (coin 5). In order for a coin to cover a tile, the coin must cover up a positive area of the tile. In other words, it is not enough to simply touch the boundary of the tile. The center of the coin may be at any point of the playing area with uniform probability. You may assume that (1) the coin always comes to a rest lying flat, and (2) the player is good enough to guarantee that the center of the coin will always come to rest on the playing area (or the boundary).

The probability of a coin covering a certain number of tiles depends on the tile and coin sizes, as well as the number of rows and columns of tiles in the playing area. In this problem, you will be required to write a program which computes the probabilities of a coin covering a certain number of tiles.

Input

The first line of input is an integer specifying the number of cases to follow. For each case, you will be given 4 integers m, n, t, and c on a single line, separated by spaces. The playing area consists of m rows and n columns of tiles, each having side length t. The diameter of the coin used is c. You may assume that 1 <= m, n <= 5000, and 1 <= c < t <= 1000.

Output

For each case, print the case number on its own line. This is followed by the probability of a coin covering 1 tile, 2 tiles, 3 tiles, and 4 tiles each on its own line. The probability should be expressed as a percentage rounded to 4 decimal places. Use the format as specified in the sample output. You should use double-precision floating-point numbers to perform the calculations. "Negative zeros" should be printed without the negative sign. 

Separate the output of consecutive cases by a blank line.

Sample Input

3
5 5 10 3
7 4 25 20
10 10 10 4

Sample Output

Case 1:
Probability of covering 1 tile  = 57.7600%
Probability of covering 2 tiles = 36.4800%
Probability of covering 3 tiles = 1.2361%
Probability of covering 4 tiles = 4.5239%

Case 2:
Probability of covering 1 tile  = 12.5714%
Probability of covering 2 tiles = 46.2857%
Probability of covering 3 tiles = 8.8293%
Probability of covering 4 tiles = 32.3135%

Case 3:
Probability of covering 1 tile  = 40.9600%
Probability of covering 2 tiles = 46.0800%
Probability of covering 3 tiles = 2.7812%
Probability of covering 4 tiles = 10.1788%

Source

Rocky Mountain 2007


题意为:

有n行,m列的长度为t的正方形组成的矩形(正方形的个数为n*m) ,给定一个直径为c的硬币,抛在矩形上,可能覆盖的小正方形个数为1,2,3,4(如上图),  问分别覆盖1,2,3,4个小正方形的概率是多少,保证圆心必须在矩形内,可以在边界上。


貌似是高中的数学题目,现在做起来太吃力了。。在网上搜了几篇解题报告,都是直接给出公式求解,没有具体的步骤,公式怎么来的。。。搜遍了全网...终于找到一个PPT是专门讲解此题的,看完就知道怎么做了,太感谢原作者了,下面也会引用到PPT中的内容(PS:不知道原作者是谁,没办法给出地址)。

思路为:圆心的可行面积,除以总面积,就是每种情况下的概率了。


如图5*5的矩形

红色代表硬币覆盖一个正方形的圆心可行面积。

蓝色代表硬币覆盖两个正放行的圆心可行面积。

白色代表硬币覆盖三个正方形的圆心可行面积。

绿色代表硬币覆盖四个正方形的圆心可行面积。 这个应该能看懂,对于每种可行面积,找边界连接就可以了。


情形1:

红色覆盖面积(覆盖一个正方形):

这样的面积一共有三种情况


第一种是在角上的,一共有四个这样的面积(四个角),每个面积是边长为(t-c/2) 的正方形 , 这种情况下的红色面积为 d11= (t-c/2) *(t-c/2) *4

第二种是在边上的,上边的边有(m-2)个,下面也一样,左边的边有(n-2)个,右边也一样,所以一共有(m-2+n-2)*2 个,每个面积为长为t-c宽为t-c/2的矩形,这种情况下的红色面积为  d12=(t-c/2)*(t-c) *(m+n-4)*2;

第三种是既不在角也不在边上的,一共有(总个数-前两种情况下的个数)n*m-(2*(n+m)-4)个,每个的面积为(t-c)*(t-c),double d13=(t-c)*(t-c)*(n*m-(2*(n+m)-4));

所以情形1的可行面积为三种情况的面积和,area[1]=d11+d12+d13。


情形2:

蓝色覆盖面积(覆盖两个正方形)

这样的面积一共有两种情况


第一种是靠着边的,上边有m-1个,下边也一样,左边有n-1个,右边也一样,一共有(m-1)*2+(n-1)*2个,每个面积为c*(t-c/2),d21=double d21=c*(t-c/2)*((m-1)*2+(n-1)*2);

第二种时不靠边的,个数为(总个数—靠边的),总个数=(n-1)*m+(m-1)*n, 看图就知道为什么了,每个面积为c*(t-c),d22=double d22=c*(t-c)*((m-1)*n+(n-1)*m-(m-1)*2-(n-1)*2);

area[2]= d21+d22;


情形3:

白色覆盖面积(覆盖三个正方形)



四个小白色看成一个白色面积,面积为c*c-PI*(c/2)*(c/2) ,这样的面积一共有(n-1)*(m-1)个。

area[3]=(c*c-PI*(c/2)*(c/2))*(n-1)*(m-1);


情形4:

绿色覆盖面积(上图中的绿色部分,覆盖四个三角形)

面积为 PI*(c/2)*(c/2) ,这样的面积一共有(n-1)*(m-1)个。

area[4]=PI*c*c/4*(n-1)*(m-1);


这样area[i]/总面积即为每种情行下的概率了。

代码:

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
double area[5];
const double PI=acos(-1.0);
double n,m,t,c;//n行,m列,t小方块的边长,c硬币直径

int main()
{
    int cas;cin>>cas;
    for(int i=1;i<=cas;i++)
    {
        cin>>n>>m>>t>>c;
        area[0]=t*t*n*m;//总面积
        double d11=(t-c/2)*(t-c/2)*4;//角上的四个
        double d12=(t-c/2)*(t-c)*(n+m-4)*2;//外边一圈除去角上的
        double d13=(t-c)*(t-c)*(n*m-(2*(n+m)-4));//除去一圈里面的
        area[1]=d11+d12+d13;

        double d21=c*(t-c/2)*((m-1)*2+(n-1)*2);//在边上的
        double d22=c*(t-c)*((m-1)*n+(n-1)*m-(m-1)*2-(n-1)*2);//其它上的
        area[2]=d21+d22;

        area[3]=(c*c-PI*(c/2)*(c/2))*(n-1)*(m-1);

        area[4]=PI*c*c/4*(n-1)*(m-1);

        cout<<"Case "<<i<<":"<<endl;
        for(int i=1;i<=4;i++)
        {
            cout<<"Probability of covering "<<i;
            if(i==1)
                cout<<" tile  = ";
            else
                cout<<" tiles = ";
            cout<<setiosflags(ios::fixed)<<setprecision(4)<<area[i]/area[0]*100<<"%"<<endl;
        }
        cout<<endl;
    }
    return 0;
}