原文地址:
需求:
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ù)組的
再就是代碼實(shí)現(xiàn)了:
如上數(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);
}
}