区域的个数 (坐标离散化)


区域的个数

题意:

w * h的格子上画了n条或垂直或水平的宽度为1的直线。求出这些线段将格子划分成了多少个区域。


输入:

w = 10, h = 10, n = 5

x1 = {1, 1, 4, 9, 10}

x2 = {6, 10, 4, 9, 10}

y1 = {4, 8, 1, 1, 6}

y2 = {4, 8, 10, 5, 10}

(对应于前面的例图)


输出:

6


分析:

准备好w * h的数组,并记录是否有直线通过,然后利用深度优先搜索求水坑数的方法,可以求出被分割出的区域个数。但是这个问题中w和h最大为1000000,所以没办法创建w * h的数组。因此我们要使用坐标离散化这一技巧。

将前后没有变化的行列消除后并不会影响区域的个数。

数组里只需要存储有直线的行列以及其前后的行列就足够了,这样的话大小最多6n * 6n就足够了。因此就可以创建出数组并利用搜索求出区域的个数了。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 500 + 10;

int W, H, N;
int X1[maxn], X2[maxn], Y1[maxn], Y2[maxn];
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

//填充用
bool fld[maxn * 6][maxn * 6];

//对x1, x2进行坐标离散化,并返回离散化之后的宽度
int compress(int *x1, int *x2, int w)
{
    vector<int> xs;

    for (int i = 0; i < N; i++){
        for (int d = -1; d <= 1; d++){
            int tx1 = x1[i] + d, tx2 = x2[i] + d;
            if (1 <= tx1 && tx1 <= W)
                xs.push_back(tx1);
            if (1 <= tx2 && tx2 <= W)
                xs.push_back(tx2);
        }
    }

    sort(xs.begin(), xs.end());
    xs.erase(unique(xs.begin(), xs.end()), xs.end());

    for (int i = 0; i < N; i++){
        x1[i] = find(xs.begin(), xs.end(), x1[i]) - xs.begin();
        x2[i] = find(xs.begin(), xs.end(), x2[i]) - xs.begin();
    }
    return xs.size();
}

void solve()
{
    //坐标离散化
    W = compress(X1, X2, W);
    H = compress(Y1, Y2, H);

    //填充有直线的部分
    memset(fld, 0, sizeof(fld));
    for (int i = 0; i < N; i++){
        for (int y = Y1[i]; y <= Y2[i]; y++){
            for (int x = X1[i]; x <= X2[i]; x++){
                fld[y][x] = true;
            }
        }
    }

    //求区域的个数
    int ans = 0;
    for (int y = 0; y < H; y++){
        for (int x = 0; x < W; x++){
            if (fld[y][x])
                continue;
            ans++;

            //宽度优先搜索
            queue<pair<int, int> > que;
            que.push(make_pair(x, y));
            while (!que.empty()){
                int sx = que.front().first, sy = que.front().second;
                que.pop();

                for (int i = 0; i < 4; i++){
                    int tx = sx + dx[i], ty = sy + dy[i];
                    if (tx < 0 || W <= tx || ty < 0 || H <= ty)
                        continue;
                    if (fld[ty][tx])
                        continue;
                    que.push(make_pair(tx, ty));
                    fld[ty][tx] = true;
                }
            }
        }
    }
    printf("%d\n", ans);
}

int main()
{
    scanf("%d%d%d", &W, &H, &N);
    for (int i = 0; i < N; i++)
        scanf("%d", &X1[i]);
    for (int i = 0; i < N; i++)
        scanf("%d", &X2[i]);
    for (int i = 0; i < N; i++)
        scanf("%d", &Y1[i]);
    for (int i = 0; i < N; i++)
        scanf("%d", &Y2[i]);
    solve();
    return 0;
}



你可能感兴趣的:(区域的个数 (坐标离散化))