F. Yet another 2D Walking--Codeforces Round #515 (Div. 3)【dp】

版权声明: https://blog.csdn.net/qq_40791842/article/details/83043501

                                    F. Yet another 2D Walking

                                                                           time limit per test:4 seconds

                                                                           memory limit per test:256 megabytes

                                                                           input:standard input

                                                                           output:standard output

Maksim walks on a Cartesian plane. Initially, he stands at the point (0,0) and in one move he can go to any of four adjacent points (left, right, up, down). For example, if Maksim is currently at the point(0,0) , he can go to any of the following points in one move:

  • (1,0)(1,0) ;
  • (0,1)(0,1) ;
  • (−1,0)(−1,0) ;
  • (0,−1)(0,−1) .

There are also nn distinct key points at this plane. The ii -th point is pi=(xi,yi). It is guaranteed that 0≤xiand 0≤yi0≤yi and there is no key point (0,0) .

Let the first level points be such points that max(xi,yi)=1, the second level points be such points that max(xi,yi)=2and so on. Maksim wants to visit all the key points. But he shouldn't visit points of level i+1 if he does not visit all the points of level ii . He starts visiting the points from the minimum level of point from the given set.

The distance between two points (x1,y1)and (x2,y2)is |x1−x2|+|y1−y2|where |v| is the absolute value of v .

Maksim wants to visit all the key points in such a way that the total distance he walks will be minimum possible. Your task is to find this distance.

If you are Python programmer, consider using PyPy instead of Python when you submit your code.

Input

The first line of the input contains one integer nn (1≤n≤200000 ) — the number of key points.

Each of the next nn lines contains two integers xi, yiyi (0≤xi,yi≤1000000000 ) — x -coordinate of the key point pi and y -coordinate of the key point pi . It is guaranteed that all the points are distinct and the point(0,0) is not in this set.

Output

Print one integer — the minimum possible total distance Maksim has to travel if he needs to visit all key points in a way described above.

Examples

Input

8
2 2
1 4
2 3
3 1
3 4
1 1
4 3
1 2

Output

15

Input

5
2 1
1 0
2 0
3 2
0 3

Output

9

Note

The picture corresponding to the first example:

There is one of the possible answers of length 15 .

The picture corresponding to the second example:

There is one of the possible answers of length 9 .

题意:给定第一象限内的n个点,将max(xi,yi)值相同的点定为level(max(xi,yi)),移动是只能是上下左右方向移动,求一条最短路线访问到所有的点,并且保证在访问level(i+1)的点之前访问完所有的level(i)的点;

解法:根据题目要求,必须访问完同一个level的点才能访问下一个level.对于level(t)中的所有点,其实是满足坐标形如(xi,t)或(t,yi),其中xi<=t,yi<=t;将同一个level的点从所下至上,从右至左排序,以由贪心可知要使路径长度最短,必然从排序后的第一个点开始依次访问该level的点,或从最后一个点开始逆序依次访问至第一个,所以访问同一level中的所有点的路径长度不变,直接将其加入到结果中;

还有一部分路径就是level(i)与level(i+1)之间的所有路径,要使这些路径之和最小,相邻两个level之间的路径只有四种情况,即:

1)前一个level的第一个点到后一个level的第一个点;

2)前一个level的最后一个点到后一个level的第一个点;

3)前一个level的第一个点到后一个level的最后一个点;

4)前一个level的最后一个点到后一个level的最后一个点;

求这些路径的组合使总路径长度最小,dp一下就好了,dp[i][0]表示到达level(i)的第一个点的最小路径,dp[i][1]表示到达level(i)的最后一个点的最小路径;

附代码:

#include<bits/stdc++.h>

using namespace std;

#define pii pair<int, int>
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define per(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a,b) for(int i=a;i>=b;i--)
#define all(x) x.begin(),x.end()
#define PER(i,x) for(auto i=x.begin();i!=x.end();i++)
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
typedef long long ll;
const double eps=1.0e-5;
const int maxn=200000+10;

int n,len=1,t=1;
ll dp[maxn][2],ans=0;
struct node{int x,y;}a[maxn],tmp;
vector<node> vec[maxn];

bool cmp(node a,node b)
{
	if(max(a.x,a.y)==max(b.x,b.y)) return a.x==b.x?a.y<b.y:a.x>b.x;
	return max(a.x,a.y)<max(b.x,b.y);
}

ll solve(ll tmp){return tmp>=0?tmp:-tmp;}

ll get_remain()
{
	dp[1][0]=dp[1][1]=0;
	per(i,1,len){
		ll dis00=solve(vec[i-1][0].x-vec[i][0].x)+solve(vec[i-1][0].y-vec[i][0].y);
		ll dis01=solve(vec[i-1][0].x-vec[i][1].x)+solve(vec[i-1][0].y-vec[i][1].y);
		ll dis10=solve(vec[i-1][1].x-vec[i][0].x)+solve(vec[i-1][1].y-vec[i][0].y);
		ll dis11=solve(vec[i-1][1].x-vec[i][1].x)+solve(vec[i-1][1].y-vec[i][1].y);
		dp[i][0]=min(dp[i-1][0]+dis10,dp[i-1][1]+dis00);
		dp[i][1]=min(dp[i-1][1]+dis01,dp[i-1][0]+dis11);
	}
	return min(dp[len][0],dp[len][1]);
}

void init()
{
	tmp.x=tmp.y=0;
	vec[0].push_back(tmp);vec[0].push_back(tmp);
	scanf("%d",&n);
	per(i,1,n) scanf("%d%d",&a[i].x,&a[i].y);
	sort(a+1,a+n+1,cmp);
}

int main()
{
	init();
	while(t<=n){
		vec[len].push_back(a[t]);
		
		int fir=t;
		while(t<n&&max(a[t+1].x,a[t+1].y)==max(a[fir].x,a[fir].y)) t++;
		vec[len++].push_back(a[t]);
		
		ans+=(solve((ll)(a[t].x-a[fir].x))+solve((ll)(a[t].y-a[fir].y)));
		t++;
	}
	len--;
	ans+=get_remain();
	printf("%lld\n",ans);
	
}

猜你喜欢

转载自blog.csdn.net/qq_40791842/article/details/83043501