POJ 1151 Atlantis(离散化+扫描线)

题目大意:

求N个矩形的并的总面积。http://poj.org/problem?id=1151

参考了黑书上讲离散化的那两页,想到了上学期学的计算机图形学里的多边形填充算法。

src:

/********************************************************************
	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 (http://blog.csdn.net/Justme0)
	
	purpose:	http://poj.org/problem?id=1151
				求矩形的并的总面积
*********************************************************************/

// #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里,而且这样也便于调试。我尽量不用 全局变量,这样各函数调用时消息的传递就很明确了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值