多边形

A histogram is a simple rectilinear polygon whose boundary consists of two chains such that the upper
chain is monotone with respect to the horizontal axis and the lower chain is a horizontal line segment,
called the base segment (See Figure 1).
Figure 1. A histogram and its base segment (v0, v1)
Let P be a histogram specified by a list (v0, v1, . . . , vn−1) of vertices in the counterclockwise order
along the boundary such that its base segment is (v0, v1). An edge ei
is a line segment connecting two
vertices vi and vi+1, where i = 0,1, . . . , n − 1 and vn = v0.
A path inside P is a simple path which does not intersect the exterior of P. The length of the path
is defined as the sum of Euclidean length of the line segments of the path. The distance between two
points p and q of P is the length of the shortest path inside P between p and q. Your task is to find
the distance between v0 and each point of a given set S of points on the boundary of P. A point of
the set S is denoted by p(k, d) which represents a point q on the edge ek such that d is the distance
between vk and q.
In the histogram of Figure 1, the shortest path between v0 and q1 = p(10,2) is a polygonal chain
connecting v0, v14, v12 and q1 in that order, and its length is 8.595242. The shortest path between v0
and q2 = p(1,1) is a segment directly connecting v0 and q2 with length 15.033296.
Given a histogram P with n vertices and a set S of m points on the boundary of P, write a program
to find the distances between v0 and all points of S.
Input
Your program is to read from standard input. The input consists of T test cases. The number of test
cases T is given in the first line of the input. Each test case starts with a line containing an integer,
n (4 ≤ n ≤ 100,000), where n is the number of vertices of a histogram P = (v0, v1, . . . , vn−1). In
the following n lines, each of the n vertices of P is given line by line from v0 to vn−1. Each vertex is
represented by two numbers, which are the x-coordinate and the y-coordinate of the vertex, respectively.
Each coordinate is given as an integer between 0 and 1,000,000, inclusively. Notice that (v0, v1) is the
base segment. The next line contains an integer m (1 ≤ m ≤ 100,000) which is the size of a set S given
as your task. In the following m lines. Each point p(k, d) of S is given line by line, and is represented
by two integers k and d, where 0 ≤ k ≤ n − 1 and 0 ≤ d < the length of edge ek. All points in the set
S are distinct.
Output
Your program is to write to standard output. Print exactly one line for each test case. The line should
contain exactly one real value which is the sum of the distances between v0 and all points of S. Your
output must contain the first digit after the decimal point, rounded off from the second digit. If each
result is within an error range, 0.1, it will be considered correct. The Euclidean distance between two
points p = (x1, y1) and q = (x2, y2) is √
(x2 − x1)
2 + (y2 − y1)
2.
The following shows sample input and output for two test cases.
Sample Input
2
16
0 0
15 0
15 4
13 4
13 6
10 6
10 2
7 2
7 5
6 5
6 7
3 7
3 3
2 3
2 1
0 1
2
10 2
1 1
8
100000 100000
400000 100000
400000 200000
300000 200000
300000 300000
200000 300000
200000 200000
100000 200000
8
1 0
2 0
3 0
4 0
5 0
6 0
7 0
1 50000
Sample Output
23.6
1909658.1

链接:给你一个n边形,他的每条边都平行于x轴或y轴,从最左下角顶点开始,逆时针一次给出n变形上的端点坐标,然后再给你n变形上的m个点,求最左下角的点到这m个点的最短距离之和,距离要求两点连线不能与n变形的边在内部相交。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <queue>
#include <vector>
#define MM(a,b) memset(a,b,sizeof(a));
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
#define CT continue;
#define SC scanf
const int N=1e5+10;
int cas,n,m;

double f[N];
struct Point{
    double x,y;int k,d,flag;
    void read(){
        scanf("%lf%lf",&x,&y);
    }
}p[2*N],c[2*N];

void init(int i,int k,int d)
{
    p[i]=p[k];
    if(p[k].y<p[k+1].y) p[i].y=p[k].y+d;
    if(p[k].y>p[k+1].y) p[i].y=p[k].y-d;
    if(p[k+1].x>p[k].x) p[i].x=p[k].x+d;
    if(p[k+1].x<p[k].x) p[i].x=p[k].x-d;
    p[i].k=k;
    p[i].d=d;
    p[i].flag=1;
}

double dis(Point a)
{
    return sqrt(a.x*a.x+a.y*a.y);
}

Point operator-(Point a,Point b)
{
    return (Point){a.x-b.x,a.y-b.y,0,0,0};
}

double cross(Point a,Point b)
{
    return a.x*b.y-b.x*a.y;
}

bool cmp(Point a,Point b)
{
    if(a.k!=b.k) return a.k>b.k;
    else return a.d>b.d;
}

int main()
{
    SC("%d",&cas);
    while(cas--)
    {
          SC("%d",&n);
          for(int i=0;i<n;i++) {
                p[i].read();
                p[i].k=i;
                p[i].d=0;
                p[i].flag=0;
          }
          SC("%d",&m);
          for(int i=1;i<=m;i++){
             int k,d;
             SC("%d%d",&k,&d);
             init(i+n-1,k,d);
          }
          sort(p+1,p+n+m,cmp);
          double ans=0;
          int cnt=1;
          c[1]=p[0];
          for(int i=1;i<n+m;i++){
              while(cnt>1&&cross(p[i]-c[cnt-1],c[cnt]-c[cnt-1])>=0) cnt--;
              c[++cnt]=p[i];
              f[cnt]=f[cnt-1]+dis(c[cnt]-c[cnt-1]);
              if(p[i].flag) {
                    ans+=f[cnt];
              }
          }
          printf("%.1f\n",ans);
    }
    return 0;
}

  解决:构建一个凸包

时间: 2024-10-16 21:28:10

多边形的相关文章

互测六 题解 9.18 圆润的多边形&amp;Takuji与信徒

圆润的多边形: 我们可将所求图形划分如下: 绿色部分是一凸多边形,红色部分为若干个长方形,蓝色部分为若干个扇形. 易证:1.蓝色部分的总和是一个半径为r的整圆:2.红色部分的总和=凸多边形周长*r. 那么现在就只剩下如何计算的问题. 1.对于前12.5%数据,r=0且点坐标成顺时针排列,那么直接作为凸多边形来计算即可: 2.对于前50%数据,点坐标成顺时针排列,这个部分分的做法...我也没想出来... 这是为什么呢...因为这个题,是我受了洛谷P1513的启发而脑补出来的,这道题中有"点坐标成顺

POJ 1385 计算几何 多边形重心

链接: http://poj.org/problem?id=1385 题意: 给你一个多边形,求它的重心 题解: 模板题,但是不知道为啥我的结果输出的确是-0.00 -0.00 所以我又写了个 if (ans.x == 0) ans.x = 0 感觉好傻逼 代码: 1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6

利用百度API画多边形,不能监测到百度绘图鼠标事件

var drawingManager = new BMapLib.DrawingManager(map, { isOpen: false, //是否开启绘制模式 enableDrawingTool: true, //是否显示工具栏 drawingToolOptions: { anchor: BMAP_ANCHOR_TOP_RIGHT, //位置 offset: new BMap.Size(5, 5), //偏离值 scale: 0.8, //工具栏缩放比例 //工具栏显示数据 drawingMo

动规-多边形游戏

1.题目描述 多边形游戏大概是这样的:看下面的一幅图: 有一个多边形,节点处是数字,边上是运算符,这里只考虑"+"和"*"两种,两个点的数与他们之间的运算符进行运算后的结果数构成新的节点,这样运算到最后只剩一个数,我们要求得能够运算出的最大的数. 2.代码 #include <stdio.h> #include <iostream> using namespace std; int ***m; char *op; void MinMax(in

使用GPC分解多边形样例(Generic Polygon Clipper)

使用GPC分解多边形 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源) GPC: Generic Polygon Clipper GPC支持分解多边形.多边形求差集.交集,异或.并集 GPC_DIFF,                         /* Difference                        */ GPC_INT,                          /* Intersection    

计算DXFReader中多边形的面积代码示例

在DXFReader中, 一般的多边形的面积计算绝对值 其中K表是顶点的数目,它们的坐标,用于在求和和, 所以用下面的代码就可以计算出一个封闭的多段线的区域: view source print? 01 Dim Vertex As Object 02 Dim Entity As Object 03 Dim k As Long 04 Dim i As Long 05 Dim Area As Single 06 07 With DXFReader1 08 09  For Each Entity In

图形学_多边形扫描转换_边界标志算法

边界标志算法 1. 对多边形的每一条边进行扫描转换,即对多边形边界所经过的象素作一个边界标志. 2.填充 对每条与多边形相交的扫描线,按从左到右的顺序,逐个访问该扫描线上的象素. 取一个布尔变量inside来指示当前点的状态,若点在多边形内,则inside为真.若点在多边形外,则inside为假. Inside 的初始值为假,每当当前访问象素为被打上标志的点,就把inside取反.对未打标志的点,inside不变. 1 #include "easyx.h" 2 #include &qu

POJ 1279 Art Gallery 半平面交 多边形的核

题意:求多边形的核的面积 套模板即可 #include <iostream> #include <cstdio> #include <cmath> #define eps 1e-18 using namespace std; const int MAXN = 1555; double a, b, c; int n, cnt; struct Point { double x, y; double operator ^(const Point &b) const {

多边形面积公式

多边形面积公式 设点顺序 (x1 y1) (x2 y2)    ... (xn yn) 则面积等于 |x1   y1 |      |x2   y2|                  |xn   yn| 0.5 * abs( |            | +   |           | + ...... +   |           | ) |x2   y2 |      |x3   y3|                  |x1   y1| 其中        |x1   y1| |

codevs:1249 多边形的面积(多边形面积计算模板)

题目描述 Description 给出一个简单多边形(没有缺口),它的边要么是垂直的,要么是水平的.要求计算多边形的面积. 多边形被放置在一个X-Y的卡笛尔平面上,它所有的边都平行于两条坐标轴之一.然后按逆时针方向给出各顶点的坐标值.所有的坐标值都是整数(因此多边形的面积也为整数). 输入描述 Input Description 输入文件第一行给出多边形的顶点数n(n≤100).接下来的几行每行给出多边形一个顶点的坐标值X和Y(都为整数并且用空格隔开).顶点按逆时针方向逐个给出.并且多边形的每一