본문 바로가기
Algorithms

Plane Sweeping 알고리즘

by OKOK 2021. 6. 21.

- 여러 개의 직사각형이 주어졌을 때, 총 넓이를 구하는 알고리즘

- 모든 지도는 직사각형임

 

트리는 다음과 같은 방식으로 수정함

1. 직사각형의 세로선 데이터를 받아옴

2. 트리의 세로선에 해당하는 구간의 노드를 구함

3. 세로선의 종류에 따라 다음과 같이 작동 시킴

    3-1. 세로선이 시작선일 경우, 해당하는 구간의 노드의 cnt값을 1증가시킴

    3-2. 세로선이 끝선일 경우, 해당하는 구간의 노드의 cnt값을 1감소시킴

4. 해당하는 구간의 노드를 포함해 다시 루트노드까지 올라가면서 다음과 같이 작동시킴

    4-1. 위치한 노드의 cnt값이 0인 경우, 하위 두 자식 노드의 sum값을 더해 위치한 노드의 sum에 저장시킴

    4-2. 위치한 노드의 cnt값이 0보다 큰 경우, 해당하는 y축 구간 크기를 sum에 저장시킴

 

#include <stdio.h>

int N;
#define MAX_N 10000

typedef struct rec
{
    int x, y1, y2, end;
} rec;

rec make_rec(int _x, int _y1, int _y2, int _end)
{
    rec t = { _x, _y1, _y2, _end };
    return t;
}

int rec_greater_than(rec* a, rec* b)
{
    return a->x != b->x ? a->x > b->x : 0;
}

int tree[65538], cnt[65538];

void update(int x, int left, int right, int nodeLeft, int nodeRight, int val)
{
    if (left > nodeRight || right < nodeLeft)
    {
        return;
    }
    if (left <= nodeLeft && right >= nodeRight)
    {
        cnt[x] += val;
    }
    else
    {
        int mid = (nodeLeft + nodeRight) >> 1;
        update(x * 2, left, right, nodeLeft, mid, val);
        update(x * 2 + 1, left, right, mid + 1, nodeRight, val);
    }
    tree[x] = 0;
    if (cnt[x] > 0)
    {
        tree[x] = nodeRight - nodeLeft + 1;
    }
    if (cnt[x] == 0 && nodeLeft < nodeRight)
    {
        tree[x] = tree[x * 2] + tree[x * 2 + 1];
    }
}

int partition(rec a[], int l, int r)
{
    rec pivot, t;
    int i, j;
    pivot = a[l];
    i = l;
    j = r + 1;

    while (1) {
        do {
            ++i;
        } while ((!rec_greater_than(&a[i], &pivot)) && i <= r);

        do {
            --j;
        } while (rec_greater_than(&a[j], &pivot));

        if (i >= j)
        {
            break;
        }
        t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    t = a[l];
    a[l] = a[j];
    a[j] = t;
    return j;
}


void quick_sort(rec a[], int l, int r)
{
    int j;

    if (l < r)
    {
        j = partition(a, l, r);
        quick_sort(a, l, j - 1);
        quick_sort(a, j + 1, r);
    }
}

int main()
{
    freopen("input.txt", "r", stdin);
    int T;
    scanf("%d", &T);

    for (int test_case = 1; test_case <= T; test_case++)
    {
        static rec v[MAX_N * 2];
        scanf("%d", &N);

        int idx = 0, i, px, ans;
        for (i = 0; i < N; i++)
        {
            int x1, y1, x2, y2;
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            v[idx++] = make_rec(x1, y1, y2, 1);
            v[idx++] = make_rec(x2, y1, y2, -1);
        }

        quick_sort(v, 0, idx - 1);
        px = v[0].x;
        ans = 0;
        for (i = 0; i < idx; i++)
        {
            ans += (v[i].x - px) * tree[1];
            update(1, v[i].y1, v[i].y2 - 1, 0, 32768, v[i].end);
            px = v[i].x;
        }
        printf("#%d ", test_case);
        printf("%d\n", ans);
    }

    return 0;
}

'Algorithms' 카테고리의 다른 글

알고리즘 문제 해결 전략2 16장 비트마스크(1)  (0) 2021.06.21
Bipartite Match 알고리즘  (0) 2021.06.21
parametric search 알고리즘  (0) 2021.06.18
Radix Sort  (0) 2021.05.14
Counting Sort  (0) 2021.05.14

댓글