2020-2021 ACM-ICPC, Asia Seoul Regional Contest-A-Autonomous Vehicle(大模拟)

2020-2021 ACM-ICPC, Asia Seoul Regional Contest-A-Autonomous Vehicle(大模拟)

题意: 给定 n n n 条线段和,第一条线段的第一个点作为起点。然后朝一个方向前进,如果遇到十字叉路口,就往当前方向的坐标走,如果走到了端点,就往回走。本题保证所有十字路口都是四路的,并且所有线段不一定连通。

思路:

先对所有线段进行预处理,先对线段进行编号,将端点,放入对应编号的容器,然后枚举所有点对,求得所有交点,将交点存入那两条相交直线对应编号的容器中(肯定会有两个)。

再用 d x [ ] dx[] dx[] d y [ ] dy[] dy[] 将四个方向按逆时针全部表示出来。根据起点所在的线段,得到初始方向。

最后根据当前点有的编号,去对应编号的容器中查找点,取方向相同且距离最短的点。得到该点并存入后,若这个点是端点,方向转 180 180 180 度,若是交点,则转 90 90 90 度。继续,直到当前点变成起点就跳出循环。

对得到的路径求长度 l e n len len t % l e n t \% len t%len 就是从起点出发的最后一圈要走的路程。稍微模一下就能出来了。

代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#include<set>
#include<cstring>
#include<string>
#include<algorithm>
#include<iomanip>
#define fi first
#define se second
//#include<stdlib.h>
//#include <time.h>
//srand((unsigned)time(NULL));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
using namespace std;
const double eps = 1e-7;
const int N = 510;
int n;
ll t;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
int dcmp(ll x) {
    if (x == 0) return 0;
    return x > 0 ? 1 : -1;
}
struct Point{
    ll x, y;
    int id1, id2;
    Point() {id1 = id2 = -1; }
    Point (ll _x, ll _y) {
        x = _x; y = _y;
        id1 = id2 = -1;
    }
    void input() {
        scanf("%lld%lld", &x, &y);
    }
    bool operator==(const Point& b) const {
        return (x - b.x) == 0 && (y - b.y) == 0;
    }
    bool operator<(const Point& b) const {
        return dcmp(x - b.x) == 0 ? dcmp(y - b.y) < 0 : x < b.x;
    }
    Point operator-(const Point& b) const {
        return Point(x - b.x, y - b.y);
    }
    Point operator+(const Point& b) const {
        return Point(x + b.x, y + b.y);
    }
    ll operator*(const Point& b) const {
        return x * b.x + y * b.y;
    }
    ll operator^(const Point& b) const {
        return x * b.y - y * b.x;
    }
    ll dis2(Point p) {
        return (*this - p) * (*this - p);
    }
};
struct Line{
    Point s, e;
    int id;
    Line() {}
    Line(Point _s, Point _e) {
        s = _s; e = _e;
    }
    int segcrossseg(Line v) {
        int d1 = dcmp((e - s) ^ (v.s - s));
        int d2 = dcmp((e - s) ^ (v.e - s));
        int d3 = dcmp((v.e - v.s) ^ (s - v.s));
        int d4 = dcmp((v.e - v.s) ^ (e - v.s));
        if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2) return 2;
        return (d1 == 0 && dcmp((v.s - s) * (v.s - e)) <= 0) ||
               (d2 == 0 && dcmp((v.e - s) * (v.e - e)) <= 0) ||
               (d3 == 0 && dcmp((s - v.s) * (s - v.e)) <= 0) ||
               (d4 == 0 && dcmp((e - v.s) * (e - v.e)) <= 0);
    }
    Point crossPoint(Line v) {
        ll a1 = (v.e - v.s) ^ (s - v.s);
        ll a2 = (v.e - v.s) ^ (e - v.s);
        return Point((s.x * a2 - e.x * a1) / (a2 - a1), (s.y * a2 - e.y * a1) / (a2 - a1));
    }
}li[N];
vector<Point> g[N];
int main() {
    scanf("%d%lld", &n, &t);
//    vector<Point> all;
    set<Point> p1, p2; //p1是所有的端点,p2是所有的交点
    for (int i = 1; i <= n; i++) {
        li[i].id = i;
        li[i].s.input();
        li[i].e.input();
        li[i].s.id1 = i; li[i].s.id2 = i;
        li[i].e.id1 = i; li[i].e.id2 = i;
        g[i].push_back(li[i].s);
        g[i].push_back(li[i].e);
//        all.push_back(li[i].s);
//        all.push_back(li[i].e);
        p1.insert(li[i].s);
        p1.insert(li[i].e);
    }
    Point st = li[1].s;
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            int ok = li[i].segcrossseg(li[j]);
            if (ok == 2) {
                Point tp = li[i].crossPoint(li[j]);
                tp.id1 = li[i].id; tp.id2 = li[j].id;
                p2.insert(tp);
                g[li[i].id].push_back(tp);
                g[li[j].id].push_back(tp);
//                all.push_back(tp);
            }
        }
    }
//    for (Point now : p2) {
//        printf("%lld %lld -%d -%d\n", now.x, now.y, now.id1, now.id2);
//    }
    int dir; //当前的方向
    Point tp = li[1].e - li[1].s;
    tp.x = dcmp(tp.x);
    tp.y = dcmp(tp.y);
    for (int i = 0; i < 4; i++) {
        if (dx[i] == tp.x && dy[i] == tp.y) {
            dir = i;
            break;
        }
    }
//    printf("%d\n", dir);
    vector<Point> road;
    road.push_back(st);
    Point now = st;
//    cout << now.id1 << " " << now.id2 << "\n";
    int f1 = 0;
    while (true) {
        int cc = 1;
        int a[2] = {0}; a[0] = now.id1;
        if (now.id2 != now.id1) {
            cc++; a[1] = now.id2;
        }
        bool f = false;
        Point best;
        for (int k = 0; k < cc; k++) {
            int id = a[k];
            for (int i = 0; i < (int)g[id].size(); i++) {
                Point nx = g[id][i];
                if (nx == now) continue;
                Point lv = nx - now;
                Point lv_dir = Point(dx[dir], dy[dir]);
                int status = lv * lv_dir;
                if (status > 0) {
                    if (f) {
                        if (now.dis2(nx) < now.dis2(best)) {
                            best = nx;
                        }
                    }
                    else {
                        f = true;
                        best = nx;
                    }
                }
            }
        }
        if (p1.find(best) != p1.end())
            dir = (dir + 2) % 4;
        else
            dir = (dir + 1) % 4;
        road.push_back(best);
        now = best;
        if (best == st) break;
    }
//    for (int i = 0; i < (int)road.size(); i++) {
//        printf("%lld %lld\n", road[i].x, road[i].y);
//    }
    ll len = 0;
    for (int i = 1; i < (int)road.size(); i++) {
        Point r1 = road[i], r2 = road[i - 1];
        ll tmp = abs(r1.x - r2.x) + abs(r1.y - r2.y);
        len += tmp;
    }
//    printf("%lld\n", len);
    ll last = t % len;
    if (last == 0) {
        printf("%d %d\n", st.x, st.y);
    }
    else {
        for (int i = 1; i < (int)road.size(); i++) {
            Point r1 = road[i - 1], r2 = road[i];
            ll tmp = abs(r1.x - r2.x) + abs(r1.y - r2.y);
            if (last > tmp) {
                last -= tmp;
            }
            else {
                Point lv = r2 - r1;
                int dd = 0;
                for (int j = 0; j < 4; j++) {
                    Point lv_dir = Point(dx[j], dy[j]);
                    if (lv * lv_dir > 0) {
                        dd = j;
                        break;
                    }
                }
                ll add_x = dx[dd] * last;
                ll add_y = dy[dd] * last;
                printf("%lld %lld\n", r1.x + add_x, r1.y + add_y);
                break;
            }
        }
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值