题目来源: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("\n");

    }
    return 0;
}