zoukankan      html  css  js  c++  java
  • 圈水池(凸包入门)

    圈水池

    时间限制:3000 ms  |           内存限制:65535 KB
    难度:4
    描述
    有一个牧场,牧场上有很多个供水装置,现在牧场的主人想要用篱笆把这些供水装置圈起来,以防止不是自己的牲畜来喝水,各个水池都标有各自的坐标,现在要你写一个程序利用最短的篱笆将这些供水装置圈起来!(篱笆足够多,并且长度可变)
    输入
    第一行输入的是N,代表用N组测试数据(1<=N<=10)
    第二行输入的是m,代表本组测试数据共有m个供水装置(3<=m<=100)
    接下来m行代表的是各个供水装置的横纵坐标
    输出
    输出各个篱笆经过各个供水装置的坐标点,并且按照x轴坐标值从小到大输出,如果x轴坐标值相同,再安照y轴坐标值从小到大输出
    样例输入
    1
    4
    0 0
    1 1
    2 3
    3 0
    
    样例输出
    0 0
    2 3
    3 0

    题解:用到了差积的特性,如果差积为负就是顺时针转,如果为正就是逆时针,如果为0就是共线;

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 struct Node{
     8     int x,y;
     9     friend int operator < (Node a,Node b){
    10         if(a.x<b.x||(a.x==b.x&&a.y<b.y))return 1;
    11         else return 0;
    12     } 
    13 };
    14 int chaji(Node a,Node b,Node c){
    15     return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
    16 }
    17 Node a[110],ans[110];
    18 int main(){
    19     int N,m;
    20     scanf("%d",&N);
    21     while(N--){
    22         scanf("%d",&m);
    23         for(int i=0;i<m;i++)scanf("%d%d",&a[i].x,&a[i].y);
    24         sort(a,a+m);
    25         int k=0;
    26         for(int i=0;i<m;i++){
    27             while(k>1&&chaji(ans[k-2],ans[k-1],a[i])<=0)k--;
    28             ans[k++]=a[i];
    29         }
    30         int t=k;
    31         for(int i=m-1;i>=0;i--){
    32             while(k>t&&chaji(ans[k-2],ans[k-1],a[i])<=0)k--;
    33             ans[k++]=a[i];
    34         }
    35         k--;
    36         sort(ans,ans+k);
    37         for(int i=0;i<k;i++)printf("%d %d
    ",ans[i].x,ans[i].y);
    38     }
    39     return 0;
    40 }

     另一种写法:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 struct Point{
     8     double x,y;
     9 Point(double x=0,double y=0):x(x),y(y){}
    10 };
    11 typedef Point Vector;
    12 bool operator < (Vector a,Vector b){
    13     return a.x<b.x||(a.x==b.x&&a.y<b.y);
    14 }
    15 Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
    16 double Cross(Vector a,Vector b){
    17     return a.x*b.y-a.y*b.x;
    18 }
    19 Point a[110],ans[110];
    20 int main(){
    21     int N,m;
    22     scanf("%d",&N);
    23     while(N--){
    24         scanf("%d",&m);
    25         for(int i=0;i<m;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
    26         sort(a,a+m);
    27         int k=0;
    28         for(int i=0;i<m;i++){
    29             while(k>1&&Cross(ans[k-1]-ans[k-2],a[i]-ans[k-2])<=0)k--;
    30             ans[k++]=a[i];
    31         }
    32         int t=k;
    33         for(int i=m-1;i>=0;i--){
    34             while(k>t&&Cross(ans[k-1]-ans[k-2],a[i]-ans[k-2])<=0)k--;
    35             ans[k++]=a[i];
    36         }
    37         k--;
    38         sort(ans,ans+k);
    39         for(int i=0;i<k;i++)printf("%.0lf %.0lf
    ",ans[i].x,ans[i].y);
    40     }
    41     return 0;
    42 }
  • 相关阅读:
    06.数组模拟栈-简易计算器
    05.单向环形链表应用 -- 约瑟夫环
    02.数组模拟环形队列
    01.稀疏矩阵与二维数组相互转化
    大数字相乘
    13.打包发布
    悦苗园公益活动
    程序猿打招自己的电子图书馆
    【技能】提高网站可用性
    【微信技能】如何通过微信号知道对方微信的二维码
  • 原文地址:https://www.cnblogs.com/handsomecui/p/4929971.html
Copyright © 2011-2022 走看看