题目描述
There are only two directions in Perpendicularia: vertical and horizontal. Perpendicularia government are going to build a new secret service facility. They have some proposed facility plans and want to calculate total secured perimeter for each of them.
The total secured perimeter is calculated as the total length of the facility walls invisible for the perpendicularly-looking outside observer. The figure below shows one of the proposed plans and corresponding secured perimeter.
Write a program that calculates the total secured perimeter for the given plan of the secret service facility.
输入
The plan of the secret service facility is specified as a polygon.
The first line of the input contains one integer n | the number of vertices of the polygon (4≤n≤1000).
Each of the following n lines contains two integers xi and yi —- the coordinates of the i-th vertex(-106≤xi,yi≤106). Vertices are listed in the consecutive order.
All polygon vertices are distinct and none of them lie at the polygon’s edge. All polygon edges are either vertical (xi = xi+1) or horizontal (yi = yi+1) and none of them intersect each other.
输出
Output a single integer —- the total secured perimeter of the secret service facility.
样例输入
10
1 1
6 1
6 4
3 4
3 3
5 3
5 2
2 2
2 3
1 3
样例输出
6
题意:按顺序给出n个点的坐标,n个点连线得到一个不规则图形,求该图形中不面向外面的的边的长度之和。
思路:水题,不面向外面的边的长度,即内部面对自己的边的长度之和。可以直接计算所有边的长度之和,然后减去最外围周长。
这里用的方法是,可以找到规律,将所有竖向的边合并,将所有横向的边合并,若是最外层的边,合并重叠后必定叠了两层,因为要保证该图形是个封闭图形,就要有左右两边,上下两边,这是最基本的封闭条件。然后,重叠后多余两层的边即在内部相对了,这些边的长度即被计算到结果中的,直接对于两个一位数组,一个表示横边,一个表示竖边,我们计算每个区间被边覆盖了多少层,多余两层的减去两层外围边,剩余的加到结果中,最后的求和结果 即answer
对于区间重叠的处理,我们不需对整个区间进行更新,直接在区间的起点标记+1,终点标记-1,然后求一个前缀和,那么整个一位数组将形成一座山的形状。被重叠覆盖的位置,因为不断遇到起点+1的标记而慢慢变大,在某个区间结束时,因为遇到了-1的标记,前缀和的计算此时将被削去一层,这样模拟出来的层叠覆盖可以表示每个区间被边叠上的次数。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int x[2000006],y[2000009];
int px[1008],py[1008];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
for(int i=1; i<=n; i++)
{
scanf("%d%d",&px[i],&py[i]);
px[i]+=1000000;
py[i]+=1000000;
if(i!=1)
{
if(px[i]==px[i-1])
{
int maxy=max(py[i],py[i-1]);
int miny=min(py[i],py[i-1]);
y[miny]++;
y[maxy]--;
}
else
{
int maxx=max(px[i],px[i-1]);
int minx=min(px[i],px[i-1]);
x[minx]++;
x[maxx]--;
}
}
}
if(px[1]==px[n])
{
int maxy=max(py[1],py[n]);
int miny=min(py[1],py[n]);
y[miny]++;
y[maxy]--;
}
else
{
int maxx=max(px[1],px[n]);
int minx=min(px[1],px[n]);
x[minx]++;
x[maxx]--;
}
LL ans=0,sum=0;
for(int i=0; i<=2000000; i++)
{
x[i]+=x[i-1];
y[i]+=y[i-1];
if(x[i]>=2)ans+=x[i]-2;
if(y[i]>=2)ans+=y[i]-2;
}
printf("%lld\n",ans);
}
}