计算几何:TZOJ凸包练习

目录 

1255  1471  2946  3100  5071

1255: Surround the Trees 返回顶部

描述

There are a lot of trees in an area. A peasant wants to buy a rope to surround all these trees. So at first he must know the minimal required length of the rope. However, he does not know how to calculate it. Can you help him?
The diameter and length of the trees are omitted, which means a tree can be seen as a point. The thickness of the rope is also omitted which means a rope can be seen as a line.

There are no more than 100 trees.

输入

The input contains one or more data sets. At first line of each input data set is number of trees in this data set, it is followed by series of coordinates of the trees. Each coordinate is a positive integer pair, and each integer is less than 32767. Each pair is separated by blank.
Zero at line for number of trees terminates the input for your program.

输出

The minimal length of the rope. The precision should be 10^-2.

样例输入 

2
1 1
2 2
9
12 7
24 9
30 5
41 9
80 7
50 87
22 9
45 1
50 7
0

样例输出

2.83
243.06

思路: 

求凸包周长

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
int n;
struct point{
    double x,y;
    void input(){
      scanf("%lf%lf",&x,&y);
    }
    bool operator<(const point &a)const{
        return x<a.x||(x-a.x)<eps&&y<a.y;
    }
    double dist(point a){
    return sqrt((x-a.x)*(x-a.x)+(y-a.y)*(y-a.y));
    }
    double cross(point a,point b){
        double x1=a.x-x;
        double y1=a.y-y;
        double x2=b.x-x;
        double y2=b.y-y;
        return x1*y2-x2*y1;
    }
}e[105],s[105];
int graham(int n){
     sort(e,e+n);
     s[0]=e[0];
     s[1]=e[1];
     int pos=1;
     for(int i=2;i<n;i++){
          while(pos>0&&s[pos-1].cross(s[pos],e[i])<=0)pos--;
          s[++pos]=e[i];
     }
     int pos1=pos;
     for(int i=n-2;i>=0;i--){
          while(pos1>pos&&s[pos1-1].cross(s[pos1],e[i])<=0)pos1--;
          s[++pos1]=e[i];
     }
     return pos1;
}
int main(){
     while(~scanf("%d",&n),n){
         for(int i=0;i<n;i++){
              e[i].input();
         }
         if(n==1){
            printf("0.00\n");
            continue;
         }
         int pos=graham(n);
         double ans=s[pos-1].dist(s[0]);
         for(int i=0;i<pos-1;i++){
             ans+=s[i].dist(s[i+1]);
         }
         printf("%.2f\n",ans);
     }
}
View Code

1471: Wall 返回顶部

描述

Once upon a time there was a greedy King who ordered his chief Architect to build a wall around the King's castle. The King was so greedy, that he would not listen to his Architect's proposals to build a beautiful brick wall with a perfect shape and nice tall towers. Instead, he ordered to build the wall around the whole castle using the least amount of stone and labor, but demanded that the wall should not come closer to the castle than a certain distance. If the King finds that the Architect has used more resources to build the wall than it was absolutely necessary to satisfy those requirements, then the Architect will loose his head. Moreover, he demanded Architect to introduce at once a plan of the wall listing the exact amount of resources that are needed to build the wall.

Your task is to help poor Architect to save his head, by writing a program that will find the minimum possible length of the wall that he could build around the castle to satisfy King's requirements.
The task is somewhat simplified by the fact, that the King's castle has a polygonal shape and is situated on a flat ground. The Architect has already established a Cartesian coordinate system and has precisely measured the coordinates of all castle's vertices in feet.

输入

The first line of the input file contains two integer numbers N and L separated by a space. N (3 <= N <= 1000) is the number of vertices in the King's castle, and L (1 <= L <= 1000) is the minimal number of feet that King allows for the wall to come close to the castle.
Next N lines describe coordinates of castle's vertices in a clockwise order. Each line contains two integer numbers Xi and Yi separated by a space (-10000 <= Xi, Yi <= 10000) that represent the coordinates of ith vertex. All vertices are different and the sides of the castle do not intersect anywhere except for vertices.

输出

Write to the output file the single number that represents the minimal possible length of the wall in feet that could be built around the castle to satisfy King's requirements. You must present the integer number of feet to the King, because the floating numbers are not invented yet. However, you must round the result in such a way, that it is accurate to 8 inches (1 foot is equal to 12 inches), since the King will not tolerate larger error in the estimates.

样例输入

9 100
200 400
300 400
300 300
400 300
400 400
500 400
500 200
350 200
200 200

样例输出

 1628

提示

结果四舍五入就可以了

 思路:求凸包周长加半径l的圆周长

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
const double pi=acos(-1);
int n,l;
struct point{
    double x,y;
    void input(){
      scanf("%lf%lf",&x,&y);
    }
    bool operator<(const point &a)const{
        return x<a.x||(x-a.x)<eps&&y<a.y;
    }
    double dist(point a){
    return sqrt((x-a.x)*(x-a.x)+(y-a.y)*(y-a.y));
    }
    double cross(point a,point b){
        double x1=a.x-x;
        double y1=a.y-y;
        double x2=b.x-x;
        double y2=b.y-y;
        return x1*y2-x2*y1;
    }
}e[1005],s[1005];
double graham(int n,int l){
     if(n==1){
        return 2*pi*l;
     }
     sort(e,e+n);
     s[0]=e[0];
     s[1]=e[1];
     int pos=1;
     for(int i=2;i<n;i++){
          while(pos>0&&s[pos-1].cross(s[pos],e[i])<=0)pos--;
          s[++pos]=e[i];
     }
     int pos1=pos;
     for(int i=n-2;i>=0;i--){
          while(pos1>pos&&s[pos1-1].cross(s[pos1],e[i])<=0)pos1--;
          s[++pos1]=e[i];
     }
     double ans=s[pos1-1].dist(s[0]);
     for(int i=0;i<pos1-1;i++){
             ans+=s[i].dist(s[i+1]);
     }
     return ans+2*pi*l;
}
int main(){
     while(~scanf("%d%d",&n,&l)){
         for(int i=0;i<n;i++){
              e[i].input();
         }
         printf("%.0f\n",graham(n,l));
     }
}
View Code

2946: Convex Hull of Lattice Points 返回顶部

描述

A lattice point is a point with integer coordinates. A lattice polygon is a polygon with all vertices lattice points.


A polygon is convex if any line segment between two points of the polygon is inside (or on the boundary of) the polygon. Equivalently, the interior angle at each polygon vertex is less than 180 degrees.

For a set S, of lattice points, the convex hull is the smallest convex (lattice) polygon which contains all points of the set. (The vertices of the convex hull must be members of the set of lattice points). If all the points are on a single straight line, the convex hull will be a line segment (a degenerate polygon ?C see rightmost diagram below). In the diagrams below, the points of the set are indicated by solid dots, the vertices of the convex hull by X’s and the convex hull is drawn connecting the vertices.
Note that not all points on the convex hull polygon are vertices.

The vertices of a lattice polygon are in standard order if:
a) The first vertex is the one with the largest y value. If two vertices have the same y value, the one with the smaller x value is the first.
b) Vertices are given in clockwise order around the polygon.

Write a program that reads a set of lattice points and outputs the vertices of the convex hull of the points in standard order.

输入

The first line of input contains a single integer P, (1 ≤ P ≤ 1000), which is the number of data sets that follow. The first line of each data set contains the data set number, followed by a space, followed by a decimal integer giving the number of points N, (3 ≤ N ≤ 50), in the set. The remaining lines in the data set contain the points in the set, at most 5 points per line (the last line may have fewer). Each point consists of 2 space separated decimal integer values representing the x and y coordinates respectively.

输出

For each data set there are multiple lines of output. The first line contains a decimal integer giving the data set number followed by a single space, followed by a decimal integer giving the total number of vertices of the convex hull. The vertices of the convex hull follow, one per line in standard order. Each line contains the decimal integer x coordinate, a single space and the decimal integer y coordinate.

样例输入 

4
1 25
2 1 7 1 1 2 9 2 1 3
10 3 1 4 10 4 1 5 10 5
2 6 10 6 2 7 9 7 3 8
8 8 4 9 7 9 6 2 3 3
5 4 7 5 8 6 4 6 3 7
2 30
3 9 6 9 3 8 9 8 3 7
12 7 2 6 12 6 2 5 12 5
2 4 12 4 1 3 11 3 1 2
11 2 1 1 11 1 1 0 10 0
4 -1 10 -1 7 -2 10 -2 5 0
7 3 4 5 6 8 3 1 2 6
3 3
3 1 2 2 1 3
4 6
1 3 19 1 4 2 2 1 11 2
10 1

样例输出

1 10
4 9
7 9
10 6
10 3
9 2
7 1
2 1
1 2
1 5
2 7
2 8
3 9
6 9
12 7
12 4
10 -2
7 -2
1 0
1 3
3 2
1 3
3 1
4 4
1 3
11 2
19 1
2 1

 思路

求凸包,输出点(按x大小排序,x相同按y大小排序)

#include<bits/stdc++.h>
using namespace std;
struct point
{
    int x,y;
}e[55],s[55];
int cmp(point a,point b)
{
    return a.x<b.x||a.x==b.x&&a.y<b.y;
}
int cross(point a,point b,point c)
{
    int x1=b.x-a.x;
    int x2=c.x-a.x;
    int y1=b.y-a.y;
    int y2=c.y-a.y;
    return x1*y2-x2*y1;
}//求叉乘,叉乘的几何意义是以两向量为邻边的平行四边形的有向面积;
int graham(int n)
{
    sort(e,e+n,cmp);//排序
    s[0]=e[0];//从x最小的点开始逆时针寻找顶点
    s[1]=e[1];
    int pos=1;
    for(int i=2;i<n;i++)
    {
        while(pos>0&&cross(s[pos-1],s[pos],e[i])<=0)
            pos--;
        s[++pos]=e[i];
    }//找出按逆时针顺序的下半区的凸包顶点;
    int pos1=pos;
    for(int i=n-2;i>=0;i--)
    {
        while(pos1>pos&&cross(s[pos1-1],s[pos1],e[i])<=0)
            pos1--;
        s[++pos1]=e[i];
    }//找出按逆时针顺序的上半区的凸包顶点;
    return pos1;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int id,n;
        scanf("%d%d",&id,&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&e[i].x,&e[i].y);
        }
        int pos=graham(n);//求凸点
        printf("%d %d\n",id,pos);
        int flag=0;
        for(int i=0;i<pos;i++)
        {
            if(s[i].y>s[flag].y||s[i].y==s[flag].y&&s[i].x<s[flag].x)
                flag=i;//记录y最大(y相同时x较小)的点在是s中的位置
        }
        for(int i=flag;i>=0;i--)printf("%d %d\n",s[i].x,s[i].y);//顺时针输出点
        for(int i=pos-1;i>flag;i--)printf("%d %d\n",s[i].x,s[i].y);
    }
}
View Code

3100: 女生寝室的围墙 返回顶部

描述

古语有云:男女授受不亲,现在虽然是21世纪,但是为了管理方便,所以台州学院准备在女生寝室的外面筑一道围墙,学校把这项艰巨的任务交给了xzc,但是学校经费不多,所以能省则省,并不打算把这道修建的很漂亮,而是尽量节省材料,同时还要求围墙与每一栋寝室楼的中心不能小于一定的距离m,xzc要求找出最节省材料的方案,并求出围墙长度以购买材料。
这个任务并不简单,还好,这个女生寝室的多边形的,而且是建造的一片平地上,xzc已建立了一个坐标系,并求出了各个女生寝室楼的中心的位置并将其坐标测出,最近xzc比较忙,现在请你帮xzc计算出围墙的最短长度,也算是帮台州学院的女生们一个忙不是。

输入

多组数据以文本结束,每组数据含n+1行,第一行输入两个整数n、m,接下来的n行每行输入两个数据,x,y,分别是某个寝室楼的中心点的横坐标及纵坐标。

输出

输出最短的围墙长度。

样例输入

5 100
200 400
500 400
500 200
350 200
200 200

样例输出

1628

思路

和1471 一样,就是换了个新题面

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
const double pi=acos(-1);
int n,l;
struct point{
    double x,y;
    void input(){
      scanf("%lf%lf",&x,&y);
    }
    bool operator<(const point &a)const{
        return x<a.x||(x-a.x)<eps&&y<a.y;
    }
    double dist(point a){
    return sqrt((x-a.x)*(x-a.x)+(y-a.y)*(y-a.y));
    }
    double cross(point a,point b){
        double x1=a.x-x;
        double y1=a.y-y;
        double x2=b.x-x;
        double y2=b.y-y;
        return x1*y2-x2*y1;
    }
}e[1005],s[1005];
double graham(int n,int l){
     if(n==1){
        return 2*pi*l;
     }
     sort(e,e+n);
     s[0]=e[0];
     s[1]=e[1];
     int pos=1;
     for(int i=2;i<n;i++){
          while(pos>0&&s[pos-1].cross(s[pos],e[i])<=0)pos--;
          s[++pos]=e[i];
     }
     int pos1=pos;
     for(int i=n-2;i>=0;i--){
          while(pos1>pos&&s[pos1-1].cross(s[pos1],e[i])<=0)pos1--;
          s[++pos1]=e[i];
     }
     double ans=s[pos1-1].dist(s[0]);
     for(int i=0;i<pos1-1;i++){
             ans+=s[i].dist(s[i+1]);
     }
     return ans+2*pi*l;
}
int main(){
     while(~scanf("%d%d",&n,&l)){
         for(int i=0;i<n;i++){
              e[i].input();
         }
         printf("%.0f\n",graham(n,l));
     }
}
View Code

5071: Beauty Contest 返回顶部

描述

Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, earning the title 'Miss Cow World'. As a result, Bessie will make a tour of N (2 <= N <= 50,000) farms around the world in order to spread goodwill between farmers and their cows. For simplicity, the world will be represented as a two-dimensional plane, where each farm is located at a pair of integer coordinates (x,y), each having a value in the range -10,000 ... 10,000. No two farms share the same pair of coordinates. 

Even though Bessie travels directly in a straight line between pairs of farms, the distance between some farms can be quite large, so she wants to bring a suitcase full of hay with her so she has enough food to eat on each leg of her journey. Since Bessie refills her suitcase at every farm she visits, she wants to determine the maximum possible distance she might need to travel so she knows the size of suitcase she must bring.Help Bessie by computing the maximum distance among all pairs of farms.  

输入

* Line 1: A single integer, N 
* Lines 2..N+1: Two space-separated integers x and y specifying coordinate of each farm

输出

* Line 1: A single integer that is the squared distance between the pair of farms that are farthest apart from each other. 

样例输入

4
0 0
0 1
1 1
1 0

样例输出

2

提示

Farm 1 (0, 0) and farm 3 (1, 1) have the longest distance (square root of 2) 

题意:给n个点坐标(x,y)求点对之间的距离最大值(这里的距离是点与点x坐标差的平方+y坐标差的平方)

思路:点的数量较多不能枚举点求距离最大值。先求出点集的凸包,对于在凸多边形内部的点必然不会成为求出距离最大值的点。

在进行旋转卡壳,在O(n)时间找到点的距离最大值

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
const double pi=acos(-1);
int n,l;
struct point{
    double x,y;
    void input(){
      scanf("%lf%lf",&x,&y);
    }
    bool operator<(const point &a)const{
        return x<a.x||(x-a.x)<eps&&y<a.y;
    }
    double dist(point a){
    return (x-a.x)*(x-a.x)+(y-a.y)*(y-a.y);
    }
    double cross(point a,point b){
        double x1=a.x-x;
        double y1=a.y-y;
        double x2=b.x-x;
        double y2=b.y-y;
        return x1*y2-x2*y1;
    }
}e[50005],s[50005];
int graham(int n){
     sort(e,e+n);
     s[0]=e[0];
     s[1]=e[1];
     int pos=1;
     for(int i=2;i<n;i++){
          while(pos>0&&s[pos-1].cross(s[pos],e[i])<=0)pos--;
          s[++pos]=e[i];
     }
     int pos1=pos;
     for(int i=n-2;i>=0;i--){
          while(pos1>pos&&s[pos1-1].cross(s[pos1],e[i])<=0)pos1--;
          s[++pos1]=e[i];
     }
     return pos1;
}
int Rotating(int pos){
     int q=1;
     double ans=0;
     for(int i=0;i<=pos;i++){
        while(s[(q+1)%pos].cross(s[i],s[i+1])>s[q].cross(s[i],s[i+1])){
            q=(q+1)%pos;
        }
        ans=max(ans,s[i].dist(s[q]));
     }
     return (int)ans;
}
int main(){
         scanf("%d",&n);
         for(int i=0;i<n;i++){
              e[i].input();
         }
         int pos=graham(n);
         printf("%d",Rotating(pos));
}
View Code

猜你喜欢

转载自www.cnblogs.com/llhsbg/p/12926561.html