POJ 1696 Space Ant (计算几何 + 极角排序)

题意 :给你 n 个点和三种走的限制条件,问你最多能走多少个点。

题解 :

  1. 首先这个题我们必须猜出一个结论,就是按照极角排序之后每次选取角度最小的那个点一定能将所有的点走完
  2. 猜出这个结论以后就很容易了,无论你是用什么极角排序,还是凸包方法都可以解决这个问题了。

说明一下极角排序 : 为什么称之为极角呢? 首先要有一个极点,按照这个极点逆时针排序就好了 逆时针排序怎么做到呢 ? 很容易就联想到叉积 ,叉积就是一个判断逆时针和顺时针的东西。
注意极角排序的时候,当角度一样的时候按照距离排序这个一定要有啊

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值