ACM--寻找凸包

寻找凸包

  点集Q的凸包ch(Q)是一个最小的凸多边形P,它满足Q中的每个点或者在P的边界上,或者在P的内部。现对于给定的点集Q,求Q的凸包ch(Q)的顶点集合。

输入:

  输入有若干组测试数据。每一组测试数据的第一行上有整数n,表示该组测试数据有n个点组成的。接下来有n行,其每一行上有二个正整数,之间用一个或几个空格隔开。当输入行上只有一个数0时,表示输入结束。

输出:

  对第i组测试数据,先输出"set i:",然后在下一行上输出该凸包的顶点集合,要求先输出凸包的顶点中纵坐标最小且靠最左边的点,然后将凸包的其它顶点按顺时针方向列出。

输入样例:

6
1 1
2 2
1 3
2 3
3 1
3 3
0

输出样例:

set 1:
(1,1)(3,1)(3,3)(1,3)

//------code------

#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
#include<stack>
using namespace std;
ifstream fin("input.txt");
ofstream fout("out.txt");

int multi(int p1,int p2,int p3);
int Point[100][2];

template<typename T>
std::string toString(const T& t) {
 std::ostringstream s;
 s << t;
 return s.str();
}

int main()
{
    int n,i=0;
    fin>>n;
    while(i<n){
        fin>>Point[i][0]>>Point[i][1];
  i++;
 }
 
    int m=Point[0][1],t=0;
    for(int k=1;k<n;k++){
        if (Point[k][1]<m)
        {
            m=Point[k][1];t=k;
        }
        else if(Point[k][1]==m)
        {
            if (Point[k][0]<Point[t][0])
            {m=Point[k][1];t=k;}
        }
 }
 Point[i][0] = Point[t][0];
 Point[i][1] = Point[t][1];
 int q=i;
    stack<int> p;
    p.push(t);
    int kk=t,g=0;
    while(true)
    {
        for(int i=1;i<=n;i++)
   g= multi(kk,g,i);
        if(g==q)break;
  p.push(g);
        kk=g;
  g=0;
    }
    fout<<"Set: 1"<<endl;
    int get;
 string r="";
    while(!p.empty())
    {        
        get = p.top();
  r = "("+toString(Point[get][0])+","+toString(Point[get][1])+")"+r;
        p.pop();
    }
 fout<<r;
}

int multi(int p1,int p2,int p3)
{
    int v;
 int v1x=Point[p2][0]-Point[p1][0],
  v1y=Point[p2][1]-Point[p1][1],
  v2x=Point[p3][0]-Point[p1][0],
  v2y=Point[p3][1]-Point[p1][1];
 if(p1==p2) return p3;
 if(p1==p3) return p2;
 else{
  v=v1x*v2y-v1y*v2x;
  if(v>0) return p2;
  if(v<0) return p3;
  if(v==0){
   if((v1x*v1x+v1y*v1y)>(v2x*v2x+v2y*v2y))
    return p2;
   else
    return p3;
  }

 }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值