Graham算法的实现

算法思路源自于《算法导论》的计算几何章节,并用此算法解决zoj 1453

#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<fstream>
#include<stack>

using namespace std;

int infinite = 1000;
point s;
double cross_mul_1(point p0,point p1,point pi){
    return (p1.x-p0.x)*(pi.y - p1.y) - (p1.y-p0.y)*(pi.x - p1.x);
}

bool cmp(const point& p1,const point& p2){
    double co1 = (p1.x - s.x) / pow((pow(p1.x - s.x,2.0)+pow(p1.y - s.y,2.0)),0.5) ;
    double co2 = (p2.x - s.x) / pow((pow(p2.x - s.x,2.0)+pow(p2.y - s.y,2.0)),0.5) ;

    if(co1>co2)
        return true;
    else if(co1 == co2){
        double d1 = pow(p1.x - s.x,2.0)+pow(p1.y-s.y,2.0);
        double d2 = pow(p2.x - s.x,2.0)+pow(p2.y-s.y,2.0);
        //在次将同一直线上的最远的点放在更前面,为了后面编程方便
        return d1 > d2;                                     
    }
    return false;
}

void graham(){
    ifstream cin("1.txt");
    int n,i,x,y;
    cin>>n;
    vector<point> v;
    double minY = infinite ,minX = infinite ,tx,ty;
    for( i=0;i<n;++i){
        point p;
        cin>>x>>y;
        if(y < minY){
            ty = minY;
            minY = y;
            y = ty;
            tx = minX;
            minX = x;
            x = tx;
        }
        else if(y == minY && x < minX){
            tx = minX;
            minX = x;
            x = tx;
        }
        if(i!=0){         //作为原点的点不加入vector中
            p.x = x;
            p.y = y; 
            v.push_back(p);
         }

    }
    s.x = minX;
    s.y = minY;

    sort(v.begin(),v.end(),cmp);        //对夹角进行排序

    stack<point> sta;
    sta.push(s);
    sta.push(v[0]);
    sta.push(v[1]);
    point p0,p1;
    double t;
    for(int i = 2;i<v.size();++i){
        p1 = sta.top();
        sta.pop();                        //这里STL很不好用啊,不能直接访问栈里的元素
        p0 = sta.top();
        sta.push(p1);
        t = cross_mul_1(p0,p1,v[i]);
        if(t == 0){
            continue;              //跳过在同一直线上较近的点
        }
        while(t < 0){
            sta.pop();

            p1 = sta.top();
            sta.pop();                        
            p0 = sta.top();
            sta.push(p1);
            t = cross_mul_1(p0,p1,v[i]);
        }
        sta.push(v[i]);
    }

    p0 = s;
    printf("( %f , %f )\n",s.x,s.y);
    double sum = 0;
    while(!sta.empty()){
        p1 = sta.top();
        printf("( %f , %f )\n",p1.x,p1.y);
        sum += pow(pow(p1.x - p0.x,2.0)+pow(p1.y-p0.y,2.0),0.5);
        p0 = p1;
        sta.pop();
    }
    cout.precision(2);
    cout<<fixed<<sum<<endl;
}



int main(){
    graham();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值