Space Ant
http://poj.org/problem?id=1696 Description The most exciting space discovery occurred at the end of the 20th century. In 1999, scientists traced down an ant-like creature in the planet Y1999 and called it M11. It has only one eye on the left side of its head and just three feet all on the right side of its body and suffers from three walking limitations:
Input The first line of the input is M, the number of test cases to be solved (1 <= M <= 10). For each test case, the first line is N, the number of plants in that test case (1 <= N <= 50), followed by N lines for each plant data. Each plant data consists of three integers: the first number is the unique plant index (1..N), followed by two positive integers x and y representing the coordinates of the plant. Plants are sorted by the increasing order on their indices in the input file. Suppose that the values of coordinates are at most 100. Output Output should have one separate line for the solution of each test case. A solution is the number of plants on the solution path, followed by the indices of visiting plants in the path in the order of their visits.
1 .凸包 去掉凸包上的点 2. 剩下的点凸包 ,去掉凸包上的点 3. 重复上述两步知道剩下的点的个数为2或1,0 4. 还有一个重要的信息是 Description 中红色标注,用来确定唯一的顺序,要不然有很多条路径,代码以后再附上
//main.cpp #pragma once #include "stdafx.h" #include "Test_1.h" int _tmain(int argc, _TCHAR* argv[]) { Reti::test(); return 0; }
// Head_1.h #pragma once
#include<iostream> #include<time.h> #include<assert.h> #include<algorithm> #include<vector> #include<map> #include<deque> #include<string> #include<List> #include<iterator>
// Test_1.h #pragma once #include<cmath> #include<stack> using namespace std; namespace Reti ; struct Point { int x; int y;
public:
friend bool operator == ( const Point & val , const Point &rt) { return (val.x == rt.x && val.y == rt.y); } bool operator < ( const Point & val ) { if( val.x < x) return 1; else if( (val.x == x && val.y < y)) { return 1; } else { return 0; } } friend ostream & operator << (ostream & out, const Point & val) { out<<" x ="<<val.x<<" y ="<<val.y<<endl; return out; } };
int dist( const Point & lf ,const Point & rt) { return ( lf.x - rt.x ) * ( lf.x - rt.x) + ( lf.y - rt.y) * ( lf.y - rt.y); }
int crossProduct(const Point & init , const Point & lf , const Point & rt) { return ( lf.x - init.x ) * ( rt.y - init.y) - ( rt.x - init.x) * ( lf.y - init.y) ; }
struct pCmp { bool operator ()( const Point & lfv ,const Point & rtv) { return ( (lfv.y < rtv.y) || (lfv.y == rtv.y && lfv.x < rtv.x ) ); } };
struct crossCmp { Point m_val;
public: crossCmp( const Point & val):m_val( val){}
bool operator() ( const Point & lf ,const Point & rt) //极角排序 { int tp = crossProduct( m_val, lf, rt); if( tp > 0) return 1; if( tp == 0 && dist( m_val ,lf) < dist(m_val, rt)) return 1; return 0; } };
class vectorCmp // comparator using in connect two hull , the point which turn left first corrspond to the last edge in outer hull is marked { Point pt_start ; Point pt_next; public: vectorCmp( const Point & val ,const Point & val2) { pt_start.x = val.x ; pt_start.y = val.y; pt_next.x = val2.x ; pt_next.y = val2.y; } bool operator() ( const Point & lf ,const Point & rt) { //cout<<" lf "<<lf<<" "<<rt<<pt_start<<pt_next<<endl; Point vector1 ,vector2 ,vector3; vector1.x = pt_next.x - pt_start.x ; vector1.y = pt_next.y - pt_start.y; vector2.x = lf.x - pt_next.x ; vector2.y = lf.y - pt_next.y; vector3.x = rt.x - pt_next.x ; vector3.y = rt.y - pt_next.y; double theta1 = ::acos( (vector1.x * vector2.x + vector1.y * vector2.y) / ( sqrt( (double)dist( pt_start, pt_next) ) * sqrt( (double)dist( pt_next ,lf) ))); double theta2 = ::acos( (vector1.x * vector3.x + vector1.y * vector3.y) / ( sqrt( (double)dist( pt_start, pt_next) ) * sqrt( (double)dist( pt_next ,rt )) )); //cout<<"theta1 ="<<theta1<<" theta2 ="<<theta2<<endl; return theta1 < theta2; } };
list<Point> point2list( Point * val, int len) { list<Point> ret; ret.clear(); for( int i = 0 ; i < len ; i++) { Point tp; tp.x = val[i].x ; tp.y = val[i].y; ret.push_back(tp); } return ret; }
void list2point(const list<Point> & val ,Point * pt) { list<Point>::const_iterator pos; int i = 0; for( pos = val.begin() ; pos != val.end(); ++pos, i++) { pt[i] = *pos; } }
void computeConvexHull( Point * val,int len ,list<Point> & conv_hull) // computing convex hull { Point * p = val; sort( p , p + len ,pCmp()); sort( p + 1, p + len ,crossCmp(p[0])); vector< Point> mtp(p ,p + len); assert( mtp.size() >= 3); stack< Point > pStack; pStack.push(mtp[0]); pStack.push(mtp[1]); {
int i = 2; while( i < mtp.size() ) { Point pt_1 ,pt; { pt_1 = pStack.top(); pStack.pop(); pt = pStack.top(); pStack.push(pt_1); }
if( crossProduct( pt_1 ,pt ,mtp[i]) <= 0) { pStack.push(mtp[ i++]); } else { pStack.pop(); } } }
cout<<"pStack size ="<<pStack.size()<<endl; { list< Point> m_ret; while( !pStack.empty()) { m_ret.push_front( pStack.top()); pStack.pop(); } conv_hull = m_ret; }
}
list<Point> getNonUsed(const list<Point> & allPoints ,const list<Point> & oneConv) { list<Point> ret; list<Point>::const_iterator pos; for( pos = allPoints.begin() ; pos != allPoints.end() ; ++pos) { if( find( oneConv.begin() ,oneConv.end() ,*pos) != oneConv.end() ){} else { ret.push_back(*pos); } } return ret; }
void conv_hull(Point *val ,int len) //computing result { vector< Point> mtp( val ,val + len); list< Point> pp( val ,val + len); int rest = mtp.size(); list<Point> pS ; vector< Point> m_result; m_result.clear(); int conv_count = 0; list< Point> hull ,nonUsed ,used; hull.clear(); nonUsed = pp; used.clear(); bool isFirst = true; while( rest > 2) { Point *hulltp = new Point[ nonUsed.size()]; list2point( nonUsed ,hulltp); computeConvexHull( hulltp, rest ,hull); cout<<" hull "<<++conv_count<<endl;
cout<<" Computing link from one extern hull to inner hull"<<endl; {
if( isFirst ) { isFirst = false; cout<<" hull.size() ="<<hull.size()<<endl; m_result.insert(m_result.end() ,hull.begin() ,hull.end()); } else { cout<<" m_result.size() ="<<m_result.size()<<endl; Point pt_s; pt_s.x = m_result[m_result.size() - 2].x ; pt_s.y = m_result[m_result.size() - 2].y; Point pt_n; pt_n.x = m_result[m_result.size() - 1].x ; pt_n.y = m_result[m_result.size() - 1].y; Point * v_tp = new Point[ hull.size()]; list2point( hull, v_tp); sort( v_tp , v_tp + hull.size() ,vectorCmp( pt_s ,pt_n)); list<Point>::iterator pos ,pos1; pos = find( hull.begin() , hull.end() ,v_tp[0]); delete []v_tp; assert( pos != hull.end() ); if( pos == hull.begin() ) { } else { list< Point> tp_1(pos ,hull.end()); pos1 = hull.begin(); while( pos1 != pos) { tp_1.insert(tp_1.end() ,*pos1); ++pos1; } hull = tp_1;
}
pos = hull.begin(); while( pos != hull.end()) { m_result.insert( m_result.end() ,*pos); ++pos; } } } copy( hull.begin() , hull.end() ,ostream_iterator<Point>(cout ,"---")); { list< Point>::iterator pos; for( pos = hull.begin() ; pos != hull.end() ; ++pos) { used.push_back(*pos); } } nonUsed = getNonUsed( point2list(val, len) ,used); rest = nonUsed.size(); delete []hulltp; }
cout<<" rest =="<<rest<<endl; // take care of the rest points what can not make to a hull assert( rest < 3); { vector< Point> tp(nonUsed.begin() ,nonUsed.end()); if( tp.size() == 1) { m_result.push_back( tp[0]); } else { //cout<<m_result[ m_result.size() -2]<<endl; sort( tp.begin() ,tp.end() ,vectorCmp(m_result[ m_result.size() -2] ,m_result[ m_result.size() -1])); m_result.push_back( tp[0]); m_result.push_back( tp[1]); }
}
cout<<" result = ________________________________"<<endl; copy( m_result.begin() , m_result.end() ,ostream_iterator<Point>(cout ,"---"));
}
void test() { //Point p[14] ; //int p1[14] = { 6 ,11 ,8 ,12 ,9 ,1 ,2 ,15 ,14, 13, 5 ,7 ,10, 3}; //int p2[14] = { 11 ,9 ,7 ,8 ,20 ,6 ,13 ,1 ,17 ,19 ,18 ,3 ,16 ,2}; //for( int i = 0 ; i < 14 ;i++) //{ // p[i].x = p1[i]; // p[i].y = p2[i]; //} //conv_hull( p ,14);
Point p[10] ; int p1[10] = { 4, 9 ,5 ,1 ,3, 6 ,10 ,8 ,2 ,7 }; int p2[10] = { 5, 8, 9, 7, 2, 3, 10, 1, 4, 6}; for( int i = 0 ; i < 10 ;i++) { p[i].x = p1[i]; p[i].y = p2[i]; } conv_hull( p ,10); }
}
注:1.对共线上点是否还需去掉还未想过 2.const_iterator 与iterator之间可以交换次序消去一个错误,具体用在哪里忘记了 |
Space Ant
最新推荐文章于 2021-08-04 00:57:54 发布