题意 :给你 n 个点和三种走的限制条件,问你最多能走多少个点。
题解 :
- 首先这个题我们必须猜出一个结论,就是按照极角排序之后每次选取角度最小的那个点一定能将所有的点走完
- 猜出这个结论以后就很容易了,无论你是用什么极角排序,还是凸包方法都可以解决这个问题了。
说明一下极角排序 : 为什么称之为极角呢? 首先要有一个极点,按照这个极点逆时针排序就好了 逆时针排序怎么做到呢 ? 很容易就联想到叉积 ,叉积就是一个判断逆时针和顺时针的东西。
注意极角排序的时候,当角度一样的时候按照距离排序这个一定要有啊
bool cmp (point a,point b) {
if (fabs(cross(a.x - init.x, a.y - init.y, b.x - init.x, b.y - init.y)) < eps) {
return dist(a, init) < dist(b, init);
}
else
return cross(a.x - init.x, a.y - init.y, b.x - init.x, b.y - init.y) > 0;
}
AC代码 :
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const double eps = 1e-8;
const double INF = 1e15 + 7;
const int maxn = 505;
struct point {
double x,y;
int id;
int order;
}p[maxn];
point init;
int n;
double dist (point a,point b) {
return sqrt ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double cross (double x1,double y1,double x2,double y2) {
return x1 * y2 - x2 * y1;
}
bool cmp (point a,point b) {
if (fabs(cross(a.x - init.x, a.y - init.y, b.x - init.x, b.y - init.y)) < eps) {
return dist(a, init) < dist(b, init);
}
else
return cross(a.x - init.x, a.y - init.y, b.x - init.x, b.y - init.y) > 0;
}
int main () {
ios_base :: sync_with_stdio(false);
int T;
cin >> T;
while (T --) {
cin >> n;
int pos = 1;
for (int i = 1 ;i <= n; ++ i) {
cin >> p[i].id >> p[i].x >> p[i].y;
if (p[1].y > p[i].y || ( fabs(p[1].y - p[i].y) < eps && p[1].x > p[i].x)) swap(p[i],p[1]);
}
pos = 1;
for (int i = 1;i <= n; ++ i) {
init = p[i];
sort (p + i + 1,p + n + 1,cmp);
}
cout << n;
for (int i = 1;i <= n; ++ i) {
cout << ' ' << p[i].id;
}
cout << endl;
}
return 0;
}