题意:对顶点圈出一个向左转的最长的罗璇, 顶点只能走过一次,罗璇没有交线;
分析:对任意点集, 都能圈出一个罗璇包含所有节点; 用叉积判断罗璇方向,圈出罗璇就行,注意输出点数和起始位置的判定
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#define MAX 10005
#define INF 100000000
#include <iostream>
#define PI acos(-1.0)
#define eps 1e-8
#define INF 1e8
using namespace std;
struct Point
{
int index;
int x, y;
Point() {}
Point(int xx, int yy):x(xx), y(yy){}
bool operator < (const Point & p)const {
if(x != p.x)
return ( x < p.x);
return y < p.y;
}
void input(){
cin>>index>>x>>y;
}
void output(){
cout<<x<<" "<<y<<endl;
}
int xmult(const Point &vec)const{
return x * vec.y - y * vec.x;
}
Point sub(const Point &p)const{
return Point(x - p.x, y - p.y);
}
}p[MAX];
vector<Point>ansArray;
int M, N;
void init(){
cin>>N;
for(int i = 0; i < N; i++){
p[i].input();
}
ansArray.clear();
sort(p, p + N);
}
void getAnsArray(){
bool v[MAX];
memset(v, 0, sizeof(v));
int m = 0, mMin = 1, j = 0, sign = 1, miny = INF;
for(int i = 0; i < N; i++){
if(p[i].y < miny){
miny = p[i].y;
j = i;
}
}
while(true){ //串完所有点
for( ; j < N && j >= 0; j+= sign){
if(!v[p[j].index]){
while(m > mMin && (ansArray[m -1].sub(ansArray[m - 2]).xmult(p[j].sub(ansArray[m - 2]))) < 0){
m --;
ansArray.pop_back();
}
m++;
ansArray.push_back(p[j]);
}
}
if(m >= N)break;
mMin = m;
sign *= -1;
j += sign;
for(int jj = 0; jj < ansArray.size(); jj++){
v[ansArray[jj].index] = true;
}
}
cout<<ansArray.size();
for(int i = 0; i < ansArray.size(); i++){
cout<<" "<<ansArray[i].index;
}cout<<endl;
}
int main()
{
cin>>M;
while(M--){
init();
getAnsArray();
}
return 0;
}