Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C. Ray Tracing 模拟

分析:

把所有的点按照他们所在地斜线分类,斜线形如 y=x+b,y=x+b 。然后模拟整个运动过程,每次都是一个斜线到另一个斜线的变换,最多有 O(max(n,m)) 的复杂度。
比赛的时候快速想出了整个思路,并且紫色渡劫成功。欢迎读者关注Codeforces id:JIBANCANYANG。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define pr(x) cout << #x << ": " << x << "  " 
#define pl(x) cout << #x << ": " << x << endl;
const int bias = int(1e5) + 13, maxn = int(2e5 + 30);

struct node {
    int x, y, d;
};

struct jibancanyang
{
    vector<node> A[maxn], B[maxn];
    int n, m, k;
    long long ans[bias];

    void fun() {
        scanf("%d%d%d", &n, &m, &k);
        memset(ans, -1, sizeof(ans));
        for (int i = 0; i < k; ++i) {
            node a;
            scanf("%d%d", &a.x, &a.y);
            a.d = i;
            A[a.y - a.x + bias].push_back(a);
            B[a.x + a.y].push_back(a);
        }

        int s = 0, t = 0, d = 1;
        long long times = 0;
        while (true) {
            int tt = t, ss = s;
            if (d == 1) {
                int y1 = t + (n - s);
                if (y1 <= m) {
                    s = n, t = y1; 
                    d = 4;
                } else {
                    s = s + (m - t), t = m;
                    d = 2;
                }
                for (auto c : A[tt - ss + bias]) {
                    if (ans[c.d] == -1) {
                        ans[c.d] = times + abs(c.y - tt); 
                    }
                }
            }
            else if (d == 2) {
                int y1 = t - (n - s);
                if (y1 >= 0) {
                    s = n, t = y1; 
                    d = 3;
                } else {
                    s = s + t, t = 0;
                    d = 1;
                }
                for (auto &c : B[tt + ss]) {
                    if (ans[c.d] == -1) {
                        ans[c.d] = times + abs(c.y - tt); 
                    }
                }
            }
            else if (d == 3) {
                int y1 = t - (s);
                if (y1 >= 0) {
                    s = 0, t = y1; 
                    d = 2;
                } else {
                    s = s - t, t = 0;
                    d = 4;
                }
                for (auto &c : A[tt - ss + bias]) {
                    if (ans[c.d] == -1) {
                        ans[c.d] = times + abs(c.y - tt); 
                    }
                }
            }
            else  {
                int y1 = t + (s);
                if (y1 <= m) {
                    s = 0, t = y1; 
                    d = 1;
                } else {
                    s = s - (m - t), t = m;
                    d = 3;
                }
                for (auto &c : B[tt + ss]) {
                    if (ans[c.d] == -1) {
                        ans[c.d] = times + abs(c.y - tt); 
                    }
                }
            }
            times += abs(s - ss);
            if (s == 0 && (t == 0 || t == m)) break;
            if (s == n && (t == 0 || t == m)) break;
        }
        for (int i = 0; i < k; ++i) {
            printf("%lld\n", ans[i]);
        }
    }
}ac;

int main()
{
#ifdef LOCAL
    freopen("inn.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif
    ac.fun();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值