1. 程式人生 > >算法復習之坐標離散化

算法復習之坐標離散化

個數 find 寬度 ostream 利用 mes lan oid push

離散化概念

例子:

1.

描述: 在桌子上放了N個平行於坐標軸的矩形,這N個矩形可能有互相覆蓋的部分,求它們組成的圖形的面積。

輸入格式:輸入第一行為一個數N(1<=N<=100),表示矩形的數量,下面N行,每行四個整數,分別表示每個矩形的左下角

和右上角的坐標,坐標範圍為-10^8到10^8之間的整數。

輸出格式:

輸出只有一行,一個整數,表示圖形面積。

樣例輸入:

3

1 1 4 3

2 -1 3 2

4 0 5 2

樣例輸出:

10

#include<iostream>
#include<algorithm>
using namespace std;
const
int maxn=210; int x1[maxn],y1[maxn],x2[maxn],y2[maxn],x[maxn],y[maxn]; void init() { for(int i=0; i<maxn; i++) { x1[i]=y1[i]=x2[i]=y2[i]=x[i]=y[i]=0; } } int main() { int n; while(cin>>n) { init(); for(int i=1; i<=n; i++) { cin>>x1[i]>>y1[i]>>x2[i]>>y2[i]; 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,x+2*n+1); sort(y+1,y+2*n+1); int sum=0; //枚舉每一個單位,,判斷是否符合條件 for(int i=1; i<=2*n-1; i++) for(int j=1; j<=2*n-1; j++) {
int s=((x[i+1]-x[i])*(y[i+1]-y[i])); for(int k=1; k<=n; k++) { if(x[i]>=x1[k]&&y[i]>=y1[k]&&x[i+1]<=x2[k]&&y[i+1]<=y2[k]) { sum+=s; break; } } } cout<<sum<<endl; } return 0; }

2.來自《挑戰程序設計競賽》

區域的個數

w*h的各自上畫了n條垂直或水平的寬度為1的直線,求出這些線將格子劃分成了多少個區域。

限制條件:1<=w,h<=1000000 1<=n<=500

利用數組存儲搜索即可,問題在於數的範圍太大,所以要利用坐標離散化,數組中只需存儲有直線的行列,及其前後的行列就夠了。

//離散化函數,對坐標x1,x2進行離散化,並返回離散化之後的寬度
//其中x1,x2代表一條直線開頭與結尾的列 y為行 
//重新形成一個數組
#include<iostream>
#include<algorithm>
#include<utility>
#include<vector>
int Compress(int *x1,int *x2,int w) {
    vector<int> s;//只需存前後及自身坐標
    for(int i=0; i<n; i++) {
        for(int d=-1; d<=1; d++) {
            //首先判斷前後
            int tx1=x1[i]+d;
            int tx2=x2[i]+d;
            if(1<=tx1&&tx1<=w)  s.push_back(tx1);
            if(1<=tx2&&te2<=w)  s.push_back(tx2);
            //進行排序刪除重復的
        }
    }
    sort(s.begin(),s.end());
    s.erase(unique(s.begin(),s.end()),s.end());
    //重新分配順序
    for(int i=0; i<n; i++) {
        x1[i]=find(s.begin(),s.end(),x1[i])-s.begin();
        x2[i]=find(s.begin(),s.end(),x2[i])-s.begin();
    }
   return s.size();
}

算法復習之坐標離散化