Pagini recente » Cod sursa (job #2498705) | simulare.oji.2024.bv_11_12 | Cod sursa (job #3247756) | Cod sursa (job #2744426) | Cod sursa (job #1828926)
#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;
}