Gym - 101808E Floods ACM ICPC, Damascus University Collegiate Programming Contest(2018)-E

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39396954/article/details/81906471

传送门:http://codeforces.com/gym/101808/problem/E

E-Floods

You probably heard and even saw the heavy rains that flooded the streets of Damascus recently.

Shahhoud is wondering if he should go to university or not. He asked you to find out how much rainwater is filling his street.

To make things simple, you can imagine Shahhoud's street as a 2D polyline consisting of N points. A 2D polyline is a number of points such that every point is connected to the point before it by a line segment. It is guaranteed that any vertical line crosses the polyline in at most one point.

Rain falls from above the polyline down the y axis. Your task is to calculate the total area that keeps rainwater.

The image below describes the second sample test:

Input

The first line contains a single integer T, the number of test cases.

Each test case starts with a line containing one integer N (1 ≤ N ≤ 105), the number of points in the polyline that represents the street Shahhoud lives in.

The following N lines describe the points of the polyline. The ith line contains two space separated integers xi and yi, the ith point of the polyline. (0 ≤ xi, yi ≤ 106). It is guaranteed that xi < xi + 1 for every 1 ≤ i < N.

Output

For each test case, print one line containing the total area that keeps rainwater.

Your answer will be considered correct if the relative error is less than 10 - 6.

Example

Input

2
2
1 1
2 1
7
1 1
2 0
3 1
5 5
7 2
8 3
9 0

Output

0.00000000
1.83333333

题意:给n个x坐标递增的点,求如图那样可以积水的阴影面积。

思路:看左边的图,可以考虑把每个水坑分割成三角形或者是梯形。s1的计算方法看右图,假设当前你在看x2,y2这个点,你发现x1这个点比它低,但是sta那个点限制了高度,阴影面积的计算:竖着的很好算,sta的y去-y1。横着的取大的三角形x1-x2,再乘以(y-y1)/(y2-y1)。s2和s3计算方法很朴素,就是当前计算的两个点的x差值,再乘以 限制的sta的y分别减去两个点的高度再相加(梯形里就是上底加下底),最后/2.那么接下来最后的问题就是怎么求每次切割的限制高度sta了,分别统计每个点左边最高点的y和右边最高点的y,每次取较小的那个,记为sta_y。如果这个点高度比当前读的点和下一个点都高,那就可以求s3那样的三角形,或者s2那样的矩形,如果是在两个点之间,那就是s1那种相似的计算啦。

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int maxv=1e5+5;

double ans=0;
int t,n,x[maxv],y[maxv],l[maxv],r[maxv];

int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)
			cin>>x[i]>>y[i];
		int maxx=-1;
		for(int i=1;i<=n;i++)
		{
			maxx=max(maxx,y[i]);
			l[i]=maxx;
		}
		maxx=-1;
		for(int i=n;i>=1;i--)
		{
			maxx=max(maxx,y[i]);
			r[i]=maxx;
		}
		ans=0;
		for(int i=1;i<=n-1;i++)
		{
			int down,up;
			if(y[i]<=y[i+1])
			{
				down=i;
				up=i+1;
			}
			else
			{
				down=i+1;
				up=i;
			}
			int sta=min(l[down],r[down]);
			if(sta>=y[down]&&sta>=y[up])
			{
				ans+=(double)(x[i+1]-x[i])*(double)(2*sta-y[down]-y[up])*0.5;
			}
			else if(sta>y[down])
			{
				ans+=(double)(x[i+1]-x[i])*(double)(sta-y[down])*(double)(sta-y[down])/(y[up]-y[down])*0.5;
			}
		}
		printf("%.8lf\n",ans);

	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39396954/article/details/81906471