题目来源:http://poj.org/problem?id=1696
分析:
题意:一只蚂蚁,不会向右转,现在给出平面上很多个点,求解一种走法,
能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.
思路:
先将所有的点按纵坐标从小到大进行排序,选择第一个点然后对剩下的点进行按极角从小到大排序,选择排序后的第一个点,在对剩下的点按极角从小到大进行排序以此到最后一个点。
代码如下:
#include <iostream> #include <algorithm> #include <stdlib.h> #include <iostream> #include <stdio.h> #include <string> #include <string.h> #include <vector> #include <set> #include <math.h> #include <cmath> #include <map> #include <queue> using namespace std; typedef long long ll; struct Point{ int x,y,id; }; int xmult(Point p0,Point p1,Point p2) // p0p1 向p2转 叉积形式是 p0p1X p0p2 { return (p1.x-p0.x)*(p2.y-p0.y) - (p1.y-p0.y)*(p2.x-p0.x); } int dist(Point p1,Point p2) { return ( p2.x-p1.x )*( p2.x-p1.x ) + ( p2.y-p1.y )*( p2.y-p1.y ); } const int N=60; Point List[N]; // 输入点集Q int stack[N]; int now; // 为基准点的序号 // 按极角排序,如果极角相等则按距离从小到大,sort是按从小到大排列的,故需对<符号重载 int operator<(Point p1,Point p2) { double tmp=xmult(List[now],p1,p2); //List[now]为基点 , 向p2转 if(tmp>0) return 1; else if(tmp==0 && dist( List[now], p1 ) < dist( List[now], p2 ) ) return 1; else return 0; } int cmp(Point p1,Point p2) // 先按y从小到大, y相等 则按 x 从小到大,最小的 即是最左下方 { if(p1.y != p2.y) return p1.y < p2.y; else return p1.x < p2.x; } int main() { int T,n; cin>>T; while(T--) { cin>>n; for(int i=0;i<n;i++) cin>>List[i].id>>List[i].x>>List[i].y; sort(List, List + n,cmp); // 选择y值最小的点 作为第一个点 now=0; int si=0; stack[si]=List[now].id; for(int i=1; i<n;i++) { sort(List+i,List+n); // 对List[now] 基点做 极角排序 , 选择第一个点 si++,now++; stack[si]=List[now].id; } printf("%d",n); for(int i=0;i<n;i++) { printf(" %d",stack[i]); } printf(" "); } return 0; }