Cod sursa(job #1659911)

Utilizator mrazvanRazvan Mititelu mrazvan Data 22 martie 2016 18:19:59
Problema Infasuratoare convexa Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.05 kb
//#include "Processing.h"
#include <vector>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <functional>
using namespace std::placeholders;
using namespace std;


typedef struct Point
{
	double x;
	double y;
};

struct OrderAsc
{
	bool operator() (const Point& A, const Point& B)
	{
		return A.x < B.x || (A.x == B.x && A.y < B.y);
	}
};

class Processing
{
public:
	void LoadData(const char* filePath)
	{
		ifstream f(filePath);
		int n;
		f >> n;
		for (int i = 1; i <= n; ++i)
		{
			Point p;
			f >> p.x >> p.y;
			mPoints.push_back(p);
		}
	}

	void SaveData(const char* filePath)
	{
		ofstream g(filePath);
		g << mHullResult.size() << "\n";
		g << setprecision(6) << fixed;
		for (auto p : mHullResult)
		{
			g <<p.x << " " << p.y << " \n";
		}
	}

	bool Process()
	{
		size_t nrOfPoints = mPoints.size();
		size_t hullIndex = 0;

		mHullResult.resize(2 * nrOfPoints);
		sort(mPoints.begin(), mPoints.end(), OrderAsc());

		//DebugOutput("Start => HullIndex: %d", hullIndex);

		// Build lower hull

		/*	Binders	*/																				//std::cref( )	const type& 
		for_each(mPoints.begin(), mPoints.end(), bind(&Processing::FindOptimalCrossProduct, this, _1, std::ref(hullIndex), 2));

		/*	Lambda functions	*/
		/*for_each(mPoints.begin(), mPoints.end(), [&](const Point& point)
		{
		FindOptimalCrossProduct(point, hullIndex, 2);
		});*/

		/*	Classic for loop */
		/*
		for (auto p : mPoints)
		{
		FindOptimalCrossProduct(hullIndex, 2, p);

		//	DebugOutput("HullIndex: %d => (%d,%d)", hullIndex, (int)p.x, (int)p.y);
		//	mHullResult[hullIndex++] = p;
		}
		*/


		//DebugOutput("Build upper hull => index: %d", hullIndex);

		// Build upper hull	
		const size_t limit = hullIndex + 1;
		for (int i = nrOfPoints - 2; i >= 0; i--)
		{
			auto p = mPoints[i];
			FindOptimalCrossProduct(p, hullIndex, limit);

			/*
			DebugOutput("HullIndex: %d => (%d,%d)", hullIndex, (int)p.x, (int)p.y);
			mHullResult[hullIndex++] = p;
			*/
		}

		mHullResult.resize(hullIndex);
		return true;
	}

protected:
	/*
	2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
	Returns a positive value, if OAB makes a counter-clockwise turn, negative for clockwise turn, and zero if the points are collinear.
	*/
	static double CrossProduct(const Point& O, const Point& A, const Point& B)
	{
		return (long)(A.x - O.x) * (B.y - O.y) - (long)(A.y - O.y) * (B.x - O.x);
	}

	void FindOptimalCrossProduct(const Point& point, size_t& hullIndex, const size_t limit)
	{
		while (hullIndex >= limit &&
			CrossProduct(mHullResult[hullIndex - 2], mHullResult[hullIndex - 1], point) <= 0)
		{
			hullIndex--;
		}

		//DebugOutput("HullIndex: %d => (%d,%d)", hullIndex, (int)point.x, (int)point.y);
		mHullResult[hullIndex++] = point;
	}

private:
	vector<Point> mPoints;
	vector<Point> mHullResult;

};


int main()
{
	auto proc = Processing();
	proc.LoadData("infasuratoare.in");
	proc.Process();
	proc.SaveData("infasuratoare.out");

	return 0;
}