程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 1151 Atlantis(離散化+掃描線)

POJ 1151 Atlantis(離散化+掃描線)

編輯:C++入門知識

題目大意:

求N個矩形的並的總面積。

參考了黑書上講離散化的那兩頁,想到了上學期學的計算機圖形學裡的多邊形填充算法。

src:


[cpp] 
/********************************************************************
    created:    2013/03/28
    created:    28:3:2013   11:43
    filename:   H:\PE\USA\POJ.1151.Atlantis.cpp
    file path:  H:\PE\USA
    file base:  POJ.1151.Atlantis
    file ext:   cpp
    author:     Justme0     
                   求矩形的並的總面積
*********************************************************************/ 
 
// #define ONLINE_JUDGE  
#define _CRT_SECURE_NO_WARNINGS  
#include <iostream>  
#include <algorithm>  
#include <vector>  
#include <string>  
#include <cassert>  
using namespace std; 
 
// 水平線段  
struct Horizon { 
    double xL;  // 左端點的橫坐標  
    double xR;  // 右端點的橫坐標  
    double y;   // 水平線的縱坐標  
    bool isUp;  // 矩形的上邊or下邊  
 
    Horizon() : xL(0), xR(0), y(0), isUp(false) {} 
 
    Horizon(double _xL, double _xR, double _y, bool _isUp) 
        : xL(_xL), 
        xR(_xR), 
        y(_y), 
        isUp(_isUp) {} 
 
    bool operator<(const Horizon &other) const { 
        return this->y < other.y; 
    } 
}; 
 
// 返回:輸入是否結束  
bool input(vector<double> &xVec, vector<Horizon> &hrzVec)  

    int cnt; 
    cin >> cnt; 
    if (0 == cnt) { 
        return false; 
    } 
    double Ax, Ay, Bx, By; 
    while (cnt--) { 
        cin >> Ax >> Ay >> Bx >> By; 
        xVec.push_back(Ax); 
        xVec.push_back(Bx); 
        hrzVec.push_back(Horizon(Ax, Bx, Ay, false)); 
        hrzVec.push_back(Horizon(Ax, Bx, By, true)); 
    } 
    return true; 

 
void solve(vector<double> &xVec, const vector<Horizon> &hrzVec, double &result)  

    result = 0; 
    sort(xVec.begin(), xVec.end()); 
    xVec.erase(unique(xVec.begin(), xVec.end()), xVec.end()); 
    sort(hrzVec.begin(), hrzVec.end()); 
 
    for (vector<double>::size_type i = 0; i < xVec.size() - 1; ++i) { 
        double L = xVec[i]; 
        double R = xVec[i + 1]; 
        double width = R - L; 
        assert(width > 0);   // 等於0的已unique  
 
        int count = 0;  // 計數器,正數表示被覆蓋,0表示未被覆蓋(有count個矩形覆蓋了該區域)  
        Horizon former; 
        for (vector<Horizon>::size_type j = 0; j < hrzVec.size(); ++j) { 
            Horizon current = hrzVec[j]; 
            if (current.xL <= L && R <= current.xR) { 
                assert(count >= 0); 
                if (count > 0) { 
                    double height = current.y - former.y; 
                    assert(height >= 0); 
                    result += width * height; 
                } 
                former = current; 
                current.isUp ? --count : ++count; 
                assert(count >= 0); 
            } 
        } 
        assert(count == 0); 
    } 

 
void output( int testCase, double result )  

    printf("Test case #%d\nTotal explored area: %.2f\n\n", testCase, result); 

 
int main() 

#ifndef ONLINE_JUDGE  
    freopen("cin.txt", "r", stdin); 
#endif  
 
    for (int testCase = 1; ; ++testCase) { 
        vector<double> xVec; 
        vector<Horizon> hrzVec; 
        if (!input( xVec, hrzVec)) { 
            break; 
        } 
        double result = 0; 
        solve(xVec, hrzVec, result); 
        output(testCase, result); 
    } 
 
    return 0; 

/********************************************************************
 created: 2013/03/28
 created: 28:3:2013   11:43
 filename:  H:\PE\USA\POJ.1151.Atlantis.cpp
 file path: H:\PE\USA
 file base: POJ.1151.Atlantis
 file ext: cpp
 author:  Justme0  
      求矩形的並的總面積
*********************************************************************/

// #define ONLINE_JUDGE
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cassert>
using namespace std;

// 水平線段
struct Horizon {
 double xL; // 左端點的橫坐標
 double xR; // 右端點的橫坐標
 double y; // 水平線的縱坐標
 bool isUp; // 矩形的上邊or下邊

 Horizon() : xL(0), xR(0), y(0), isUp(false) {}

 Horizon(double _xL, double _xR, double _y, bool _isUp)
  : xL(_xL),
  xR(_xR),
  y(_y),
  isUp(_isUp) {}

 bool operator<(const Horizon &other) const {
  return this->y < other.y;
 }
};

// 返回:輸入是否結束
bool input(vector<double> &xVec, vector<Horizon> &hrzVec)
{
 int cnt;
 cin >> cnt;
 if (0 == cnt) {
  return false;
 }
 double Ax, Ay, Bx, By;
 while (cnt--) {
  cin >> Ax >> Ay >> Bx >> By;
  xVec.push_back(Ax);
  xVec.push_back(Bx);
  hrzVec.push_back(Horizon(Ax, Bx, Ay, false));
  hrzVec.push_back(Horizon(Ax, Bx, By, true));
 }
 return true;
}

void solve(vector<double> &xVec, const vector<Horizon> &hrzVec, double &result)
{
 result = 0;
 sort(xVec.begin(), xVec.end());
 xVec.erase(unique(xVec.begin(), xVec.end()), xVec.end());
 sort(hrzVec.begin(), hrzVec.end());

 for (vector<double>::size_type i = 0; i < xVec.size() - 1; ++i) {
  double L = xVec[i];
  double R = xVec[i + 1];
  double width = R - L;
  assert(width > 0); // 等於0的已unique

  int count = 0; // 計數器,正數表示被覆蓋,0表示未被覆蓋(有count個矩形覆蓋了該區域)
  Horizon former;
  for (vector<Horizon>::size_type j = 0; j < hrzVec.size(); ++j) {
   Horizon current = hrzVec[j];
   if (current.xL <= L && R <= current.xR) {
    assert(count >= 0);
    if (count > 0) {
     double height = current.y - former.y;
     assert(height >= 0);
     result += width * height;
    }
    former = current;
    current.isUp ? --count : ++count;
    assert(count >= 0);
   }
  }
  assert(count == 0);
 }
}

void output( int testCase, double result )
{
 printf("Test case #%d\nTotal explored area: %.2f\n\n", testCase, result);
}

int main()
{
#ifndef ONLINE_JUDGE
 freopen("cin.txt", "r", stdin);
#endif

 for (int testCase = 1; ; ++testCase) {
  vector<double> xVec;
  vector<Horizon> hrzVec;
  if (!input( xVec, hrzVec)) {
   break;
  }
  double result = 0;
  solve(xVec, hrzVec, result);
  output(testCase, result);
 }

 return 0;
}

 

在網上看到有的ACMER把程序分為輸入、解決問題、輸出的三層結構,覺得挺好的,打算以後也這麼做,免得全擠在一個main裡,而且這樣也便於調試。我盡量不用全局變量,這樣各函數調用時消息的傳遞就很明確了。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved