算法思路源自于《算法导论》的计算几何章节,并用此算法解决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();
}