HDU OJ 1071: The area

HDU OJ 1071: The area

序言: 
刚自学了一个月的算法,算个小萌新吧(其实实在菜的一匹…)。考虑到很多知识点容易遗忘,就准备写些东西来记录一下学习过程。第一次写博客,今天先写个简单的练练手。

Problem Description:

Ignatius bought a land last week, but he didn’t know the area of the 
land because the land is enclosed by a parabola and a straight line. 
The picture below shows the area. Now given all the intersectant 
points shows in the picture, can you tell Ignatius the area of the 
land?

Note: The point P1 in the picture is the vertex of the parabola. 
这里写图片描述

Input:

The input contains several test cases. The first line of the input is 
a single integer T which is the number of test cases. T test cases 
follow. Each test case contains three intersectant points which shows 
in the picture, they are given in the order of P1, P2, P3. Each point 
is described by two floating-point numbers X and Y(0.0<=X,Y<=1000.0).

Output

For each test case, you should output the area of the land, the result 
should be rounded to 2 decimal places.

Sample Input:


5.000000 5.000000 
0.000000 0.000000 
10.000000 0.000000 
10.000000 10.000000 
1.000000 1.000000 
14.000000 8.222222

Sample Output:

33.33 
40.69

Hint 
For float may be not accurate enough, please use double instead of float.

解题思路: 
这道题目的题意很明确,就是求直线和抛物线所围的面积。输入会给定三个点P1, P2, P3,其中P1是抛物线的顶点,P2和P3是抛物线与直线的交点。我们知道,三点可以唯一确定一条抛物线,两点可以唯一确定一条直线。因此,三点给定之后,直线和抛物线亦给定。我们可以用定积分的知识求解之。值得注意的是,虽然题目规定P1, P2, P3处于第一象限,但我们也需要考察抛物线的开口方向,因为开头向上和开口向下的求解方式是有些不同的。

1.开口向下

这里写图片描述

对于开头向上的情况,红色阴影的面积等于抛物线于P2到P3的积分再减去下方梯形的面积。对于梯形面积 

S梯=(P2.y+P3.y)(P3.x−P2.x)2S梯=(P2.y+P3.y)(P3.x−P2.x)2


对于抛物线部分,由于我们已知其顶点。方便起见,我们可以采用顶点式来表达抛物线的解析式,即 

f(x)=A(x−P1.x)2+P1.yf(x)=A(x−P1.x)2+P1.y


其中,A是待定参数,选择P2或者P3代入均可解出唯一A。由此,可以写出抛物线的定积分 

∫P3.xP2.xf(x)dx=[A3(x−P2.x)3+(P1.y)x]∣∣∣P3.xP2.x∫P2.xP3.xf(x)dx=[A3(x−P2.x)3+(P1.y)x]|P2.xP3.x

2.开口向上

这里写图片描述

对于开口向下,很显然,此时如果按照开口向上的方法进行计算,会得到所求面积的相反数。因此,我们可以用取绝对值的方法将两种情况进行归并。

至此,解题思路都已经有了,其他都交给code吧。值得注意的一点是,在分析过程中一直默认P2.x < P3.x,因此在存储数据的时候记得做一个预处理。

 #include<iostream>
#include<math.h>
using namespace std;
struct zuobiao
{
    double x,y;
};
int main()
{
    //freopen("C:\\Users\\23535\\Desktop\\in.txt","r",stdin); //输入重定向,输入数据将从D盘根目录下的in.txt文件中读取 
    //freopen("C:\\Users\\23535\\Desktop\\out.txt","w",stdout); //输出重定向,输出数据将保存在D盘根目录下的out.txt文件中 
    int n;
    cin>>n;
    while(n--)
    {
        zuobiao p1,p2,p3;
        cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y;
        if(p2.x>p3.x)
        {
            zuobiao p4;
            p4=p2;
            p2=p3;
            p3=p4;
        }
        double tixing=(p2.y+p3.y)*(p3.x-p2.x)/2;
        double a=(p2.y-p1.y)/(p2.x-p1.x)/(p2.x-p1.x);
        double b=p1.x;
        double c=p1.y;
        double mianji=(a/3*pow(p3.x-b,3)+c*p3.x)-(a/3*pow(p2.x-b,3)+c*p2.x);
        printf("%.2lf\n",abs(mianji-tixing));
    }
    //fclose(stdin);//关闭重定向输入 
    //fclose(stdout);//关闭重定向输出 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hhdmw/article/details/81079590