求N個(gè)可重疊的矩形總面積

原文地址:

求n個(gè)矩形面積——坐標(biāo)離散化

需求:

n個(gè)與直角坐標(biāo)系平行的矩形,可能重疊,要求出總面積(重疊部分只算一次)


樣例
思路:

這題按照最平常的想法就是把矩形內(nèi)的標(biāo)記,然后整個(gè)圖搜索,就可以得出共覆蓋了多少范圍。但是范圍是-10^8~10^8,這么搜顯然不可能。所以要怎么樣呢?

就是把有用的點(diǎn)保存,無關(guān)的點(diǎn)壓縮。什么是有用的點(diǎn)保存,什么是無關(guān)的點(diǎn)壓縮?給出的坐標(biāo)就是有用的點(diǎn),-10^8~10^8內(nèi)的范圍內(nèi)除了給出的坐標(biāo)范圍其他全是沒用的點(diǎn),都要壓縮。

有用的值其實(shí)只有這么幾個(gè)。這些值將作為新的坐標(biāo)值重新劃分整個(gè)平面,省去中間的若干坐標(biāo)值沒有影響。我們可以將坐標(biāo)范圍“離散化”到1到200
之間的數(shù),于是一個(gè)200*200的二維數(shù)組就足夠了。

樣例:

現(xiàn)在用個(gè)小例子來模擬一下:
注意左邊的10* 7的數(shù)組是如何等價(jià)地轉(zhuǎn)化為右邊兩個(gè)4*4的數(shù)組的


image

再就是代碼實(shí)現(xiàn)了:


image

如上數(shù)據(jù)示例
x[ ]={ 1, 3, 7, 10 };
y[ ]={ 1, 2, 5, 7 };

按代碼枚舉的順序是如上圖,先看(1,1)點(diǎn), if(x[i]>=x1[k]&&y[j]>=y1[k]&&x[i+1]<=x2[k]&&y[j+1]<=y2[k])判斷是否是矩形內(nèi)的然后按順序枚舉,發(fā)現(xiàn)(1,1)點(diǎn)不是,再看(1,2)點(diǎn),s=s(x+1,y+1)-s(x,y)即框2,符合在矩形內(nèi),ans+=s,枚舉完了,就得出結(jié)果了

C語(yǔ)言代碼:

include<cstdio>
include<cstdlib>
include<algorithm>
include<iostream>
define MAXn 100
using namespace std;
int n;
long long x1[MAXn+1],y1[MAXn+1];
long long x2[MAXn+1],y2[MAXn+1];
long long x[2MAXn+1],y[2MAXn+1];
long long S,ans;
int main()
{
    scanf("%d",&n); 
    for(int i=1;i<=n;i++) 
    { 
        scanf("%I64d%I64d%I64d%I64d",&x1[i],&y1[i],&x2[i],&y2[i]); 
        x[2i-1]=x1[i]; 
        x[2i]=x2[i]; 
        y[2i-1]=y1[i];
        y[2i]=y2[i]; 
    } 
    sort(x+1,x+2n+1); 
    sort(y+1,y+2n+1); 
    for(int i=1;i<=2n-1;i++) //枚舉每一個(gè)單位橫坐標(biāo),這兩句看圖 
        for(int j=1;j<=2n-1;j++)  //枚舉每一個(gè)單位縱坐標(biāo)
        { 
            S=(x[i+1]-x[i])*(y[j+1]-y[j]);
            for(int k=1;k<=n;k++) //枚舉每一個(gè)矩形塊 
                if(x[i]>=x1[k]&&y[j]>=y1[k]&&x[i+1]<=x2[k]&&y[j+1]<=y2[k])//這句是離散化
                { ans+=S; break; }//注意這個(gè)break,用的妙
        } 
    printf("%I64d",ans); return 0; 
}

java代碼(按C語(yǔ)言版本直接移植過來):

import java.util.Scanner;

public class MainClass {

    private static void sort(int[] nums) {
        sort(nums, 0, nums.length - 1);
    }

    private static void sort(int[] nums, int startIndex, int stopIndex) {
        if (null != nums) {
            for (int i = startIndex; i < stopIndex; i++) {
                for (int j = startIndex; j < stopIndex - i; j++) {
                    if (nums[j] > nums[j + 1]) {
                        int temp = nums[j];
                        nums[j] = nums[j + 1];
                        nums[j + 1] = temp;
                    }
                }
            }

        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("請(qǐng)輸入矩形個(gè)數(shù):");
        String string = scanner.nextLine();
        int count = 0;
        try {
            count = Integer.parseInt(string);
        } catch (Exception e) {
            System.out.println("輸入錯(cuò)誤\n");
            return;
        }
        System.out.println("分別輸入" + count + "個(gè)矩形坐標(biāo),格式[lx ly rx ry]:");
        final int MAXn = 100;
        if (count > MAXn) {
            count = MAXn;
        }

        int x1[] = new int[count + 1];
        int y1[] = new int[count + 1];
        int x2[] = new int[count + 1];
        int y2[] = new int[count + 1];
        int x[] = new int[2 * count + 1];
        int y[] = new int[2 * count + 1];
        for (int i = 1; i <= count; i++) {
            x1[i] = scanner.nextInt();
            y1[i] = scanner.nextInt();
            x2[i] = scanner.nextInt();
            y2[i] = scanner.nextInt();

            x[2 * i - 1] = x1[i];
            x[2 * i] = x2[i];
            y[2 * i - 1] = y1[i];
            y[2 * i] = y2[i];
        }
        sort(x, 1, 2 * count + 1);
        sort(y, 1, 2 * count + 1);
        long S = 0, ans = 0;
        for (int i = 1; i <= 2 * count - 1; i++) // 枚舉每一個(gè)單位橫坐標(biāo),這兩句看圖
            for (int j = 1; j <= 2 * count - 1; j++) // 枚舉每一個(gè)單位縱坐標(biāo)
            {
                S = (x[i + 1] - x[i]) * (y[j + 1] - y[j]);
                for (int k = 1; k <= count; k++) // 枚舉每一個(gè)矩形塊
                    if (x[i] >= x1[k] && y[j] >= y1[k] && x[i + 1] <= x2[k] && y[j + 1] <= y2[k])// 這句是離散化
                    {
                        ans += S;
                        break;
                    } // 注意這個(gè)break,用的妙
            }
        System.out.println("ans:" + ans);
    }

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。