Loading

使用离散化处理连续数据(UVa221,UVa12171)

有时我们需要处理的数据是连续的,比如时间,距离,坐标等等。这时需要用到离散化。

比如给你个二维坐标轴,500*500,给你一堆建筑物的实数型的坐标,让你求一些东西。坐标轴上的点是无穷的,计算机没法表示,所以我们不如把重心放在这些已有的建筑物坐标上而不是整个坐标轴,因为这些数据是有限且离散的。

城市正视图(Urban Elevations, ACM/ICPC World Finals 1992, UVa221)

有一片区域有n个建筑物(n<=100),它们不一样高,你现在想知道从正面看都能看到哪些建筑物。

给定这些建筑物的x坐标,y坐标(左下角的坐标),横向宽度w,纵向深度d,高度h,你要输出所有能在正视图中看到的建筑物。

输入示例
14
160 0 30 60 30
125 0 32 28 60
95 0 27 28 40
70 35 19 55 90
0 0 60 35 80
0 40 29 20 60
35 40 25 45 80
0 67 25 20 50
0 92 90 20 80
95 38 55 12 50
95 60 60 13 30
95 80 45 25 50
165 65 15 15 25
165 85 10 15 35

输出示例
5 9 4 3 10 2 1 14

第一行为建筑物的个数n,往下n行为每一个建筑物的信息,分别是x,y,w,d,h。

最后输出不必按顺序。

此题如果说给的坐标是整数,那么我们只需要遍历x坐标轴并找出能看到的那些建筑就好了。但是输入是实数,我们没法遍历,而且其实遍历整个坐标轴需要的运算量很大。

换一个想法,把每一个建筑的x坐标和x+w都放进一个数组里,x+w就是建筑物右侧的x坐标,然后我们排序并去重。

对于一个简单的输入示例来说,做完如上操作就相当于分割了如下的若干个区间。

我们只检查相邻的两个区间,相邻的两个区间具有如下性质:

  1. 该区间要么不存在建筑物,要么存在若干个建筑物
  2. 只要是在区间中的建筑物,一定会把区间给填满,不会出现建筑物只占区间部分空间的情况

所以我们只需要对于每个建筑物,检查每个区间,判断它能不能在该区间中被正视图看到。

对于一个建筑物,只要建筑物在该区间中,并且它的前面没有一个比它更高的同时也在该区间内的建筑物就行了。

#include "iostream"
#include "cstdio"
#include <algorithm>
#define MAX 101
using namespace std;

struct Building {
    int id;
    double x, y, w, d, h;
    bool operator <(const Building& r) const{
        return x > r.x || (x==r.x && y > r.y);
    }
}b[MAX];

double x[MAX*2];
int n;

bool cover(int i, double x) {
    return b[i].x <= x && b[i].x + b[i].w >= x;
}
bool visible(int i, double x) {
    if (!cover(i, x))return false;
    for (int j = 0; j < n; j++) {
        if (b[j].y<b[i].y && b[j].h >= b[i].h && cover(j,x))return false;
    }
    return true;
}
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%lf %lf %lf %lf %lf", &b[i].x, &b[i].y, &b[i].w, &b[i].d, &b[i].h);
        b[i].id = i+1;
        x[i*2] = b[i].x; x[i * 2 + 1] = b[i].x + b[i].w;
    }
    sort(x, x+n*2);
    sort(b, b + n);
    printf("\n");
    int m = unique(x, x + n * 2)-x;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m - 1; j++) {
            if (visible(i, (x[j] + x[j + 1]) / 2)) {
                printf("%d ", b[i].id);
                break;
            }
        }
    }

    return 0;
}

雕塑(Sculpture, ACM/ICPC NWERC 2008, UVa12171)

讲真的这题我按照网上的代码写了一遍,但还是不咋懂,离散化不好想,还是三维情况,等我变聪明再来填坑吧。

参考

posted @ 2020-11-13 18:48  yudoge  阅读(234)  评论(0编辑  收藏  举报