Cod sursa(job #1828926)

Utilizator Adrian1997Radulescu Adrian Adrian1997 Data 14 decembrie 2016 08:24:30
Problema Metrou4 Scor 0
Compilator cpp Status done
Runda Arhiva ICPC Marime 3.2 kb
#include <climits>
#include <fstream>
#include <iostream>
#include <queue>
#include <bitset>
#include <vector>
#include <cmath>
#include <list>
#include <vector>
#include <algorithm>
#define INF LONG_MAX
#define DIM 150011
using namespace std;

ifstream fin("metrou4.in");
ofstream fout("metrou4.out");

int n,test_count;

struct point {
	int x_coord,y_coord;
	int num;
};

vector<point> nodes, prev_vertical_seq, current_vertical_seq;
std::vector<point> *aux = new vector<point>;

int manhattan(point A, point B){
	return abs(A.x_coord - B.x_coord) + abs(A.y_coord - B.y_coord);
}

auto cmp(point a,point b){
	return (a.x_coord == b.x_coord? (a.y_coord > b.y_coord) : (a.x_coord < b.x_coord));
}

void print_vector(vector<point> v){
	for(vector<point>::iterator it = v.begin();it != v.end();it++)
		fout << it -> x_coord << " " << it -> y_coord << "\n";
	fout << "\n";
}

auto update(){

	*aux = current_vertical_seq;

	// swap the seqencies if the second is "over the first"
	if(prev_vertical_seq.begin() -> y_coord < current_vertical_seq.rbegin() -> y_coord)
		current_vertical_seq.swap(prev_vertical_seq);

	// take two iterators from on the two sequences one from begin, one from rbegin
	// iterate as long as the curently computed manhattan distance is less than the previous ones
	long long rez = INF;

	vector<point>::reverse_iterator prev_it = prev_vertical_seq.rbegin();
	vector<point>::iterator current_it = current_vertical_seq.begin();
	for(; prev_it != prev_vertical_seq.rend() && current_it != current_vertical_seq.end() && manhattan(*prev_it,*current_it) < rez; prev_it++,current_it++)
		rez = manhattan(*prev_it,*current_it);

	return rez + current_vertical_seq.begin() -> y_coord - current_vertical_seq.rbegin() -> y_coord;
}

int main(void){

	long long sum;

	fin >> test_count;
	
	point *tmp = new point;	
	
	for(; test_count; test_count --){

		fin >> n;

		for(int i = 0; i < n; i ++){
			fin >> tmp -> x_coord >> tmp -> y_coord;
			nodes.push_back(*tmp);
		}
		
		sort(nodes.begin(),nodes.end(),cmp);

		nodes.shrink_to_fit();
		
		sum = 0;
		prev_vertical_seq.push_back(nodes[0]);
		int i = 1;
		while(i < nodes.size() && nodes[i].x_coord == nodes[0].x_coord)
			prev_vertical_seq.push_back(nodes[i]),i++;	
		
		if(i+1 == nodes.size()){
			// there are only two verticals
			long long rez = INF;
			for(vector<point> :: iterator it = prev_vertical_seq.begin(); it != prev_vertical_seq.end() 
				&& manhattan(*it,nodes[i]) < rez; it ++)
				rez = manhattan(*it,nodes[i]);
			sum += rez + prev_vertical_seq.begin() -> y_coord - prev_vertical_seq.rbegin() -> y_coord;
		}
		else{
			
			sum = prev_vertical_seq.begin() -> y_coord - prev_vertical_seq.begin() -> y_coord;
			current_vertical_seq.push_back(nodes[i]);

			for(vector<point>::iterator it = nodes.begin()+i+1; it!=nodes.end(); it++){

				if(it -> x_coord == current_vertical_seq[0].x_coord){
					// add to the sequence
					current_vertical_seq.push_back(*it);
					continue;
				}

				// we finished the current sequence
				// time to compare and finished the link with the past one

				sum += update();
			}
			sum += update();
		}

		current_vertical_seq.clear();
		prev_vertical_seq.clear();
		nodes.clear();
		fout << sum << "\n";
	}	
	
	
	


	delete tmp;
	delete aux;

	return 0;
}