ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 [ABC130F] Minimum Bounding Box

2021-07-28 15:31:38  阅读:226  来源: 互联网

标签:std 题解 ans double Minimum vi Bounding fi se


这题分讨略有点恶心啊。

题面给了一堆运动的点,要求一个时刻时正着覆盖所有点的最小矩形最小。

脑补了一下觉得这是一个单峰函数,于是想着三分,但是又不太确定,所以写。

模拟一下可以发现,很多点其实是对答案没有影响的,因为它们的运行速度都一样,所以在同一个方向上运行的点只有最左边和最右边(最上最下)的是有用的。
那么就把四个方向上的点都单独拿出来,然后找出最两边的来考虑就行了。

数据范围已经缩小到了 \(n=4 \times 2 = 8\) 了,怎么实现呢?
再次观察运动过程,其实答案在最小的时候肯定是两个点并到一块儿了。考虑两个的相对运动,互相远离的一定不可能让答案变小,而一个变大一个变小的要么最后一个维度减到 \(0\),要么一个维度被其它的给约数住,只剩下一个维度的变化,所以肯定是两个点撞在同一水平或竖直线线的时候。

那么就变成一道大力分讨题了,讨论所有相撞的时间然后代入验证就可以了。

需要讨论的相撞:

  1. 两点在水平方向上相向运动。
  2. 两点在竖直方向上相向运动。
  3. 一个往上,一个往左。
  4. 一个往上,一个往右。
  5. 一个往下,一个往左。
  6. 一个往下,一个往右。

我开始没有想得很清楚,实现很不精细,调来调去后才过的。

混乱的代码
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <utility>
#include <vector>
#include <cmath>
#define fi first
#define se second
#define mapa std::make_pair
const int N = 100005;
std::vector<std::pair<int, int> > p[5];
std::vector<std::pair<std::pair<int, int>, int> > vi;
double ans = 1e18;
char st[N][5];
int x[N], y[N], tr[256], n;
double get(double t) {
    if (t < 0) return 1e18;
    double xmax = -1e18, xmin = 1e18, ymax = -1e18, ymin = 1e18;
    for (int i = 1; i <= n; i++) {
        double nx = x[i], ny = y[i];
        if (st[i][0] == 'R') nx += t;
        else if (st[i][0] == 'L') nx -= t;
        else if (st[i][0] == 'U') ny += t;
        else ny -= t;
        xmax = std::max(nx, xmax), xmin = std::min(xmin, nx);
        ymax = std::max(ny, ymax), ymin = std::min(ny, ymin);
    }
    return (xmax - xmin) * (ymax - ymin);
}
int main(){ 
    tr['R'] = 1, tr['L'] = 2, tr['U'] = 3, tr['D'] = 4;
    std::cin >> n;
    for (int i = 1; i <= n; i++) {
        std::cin >> x[i] >> y[i] >> st[i];
        p[tr[st[i][0]]].push_back(mapa(x[i], y[i]));
    }
    for (int i = 1; i <= 4; i++) {
        int xmax = 0, xmin = 0, ymax = 0, ymin = 0;
        for (int j = 1; j < (int)p[i].size(); j++) {
            if (p[i][j].fi > p[i][xmax].fi) xmax = j;
            if (p[i][j].fi < p[i][xmin].fi) xmin = j;
            if (p[i][j].se > p[i][ymax].se) ymax = j;
            if (p[i][j].se < p[i][ymin].se) ymin = j;
        }
        if (p[i].size()) {
            vi.push_back(mapa(p[i][xmax], i)), vi.push_back(mapa(p[i][xmin], i)), 
            vi.push_back(mapa(p[i][ymax], i)), vi.push_back(mapa(p[i][ymin], i));
        }
    }
    std::cout << std::fixed << std::setprecision(10);
    ans = get(0);
    for (int i_ = 0; i_ < (int)vi.size(); i_++)
        for (int j_ = 0; j_ < (int)vi.size(); j_++) {
            int i = i_, j = j_;
            int op1 = vi[i].se, op2 = vi[j].se;
            if (op1 > op2) std::swap(i, j), std::swap(op1, op2);
            if (op1 * op2 == 2) {
                double t = -1.0 * (1.0 * vi[i].fi.fi - vi[j].fi.fi) / 2;
                ans = std::min(ans, get(t));
            }
            else if (op1 * op2 == 12) {
                double t = -1.0 * (1.0 * vi[i].fi.se - vi[j].fi.se) / 2;
                ans = std::min(ans, get(t));
            }
            if (op1 <= 2) {
                if (op2 == 3) {
                    double t = (vi[i].fi.se - vi[j].fi.se);
                    ans = std::min(ans, get(t));
                }
                else if (op2 == 4) {
                    double t = -(vi[i].fi.se - vi[j].fi.se);
                    ans = std::min(ans, get(t));  
                }
            }
            if (op2 > 2) {
                if (op1 == 1) {
                    double t = -(vi[i].fi.fi - vi[j].fi.fi);
                    ans = std::min(ans, get(t));
                }
                else if (op1 == 2) {
                    double t = (vi[i].fi.fi - vi[j].fi.fi);
                    ans = std::min(ans, get(t));  
                }
            }
        }
    std::cout << ans;
}

标签:std,题解,ans,double,Minimum,vi,Bounding,fi,se
来源: https://www.cnblogs.com/Acfboy/p/ABC130F.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有