abc353f 题解

大分讨,由于没注意到细节挂大分。

下面称大小为 \(n\times n\) 的为大格子,\(1\times 1\) 的为小格子。把 \(n\times n\) 个小格子组成的正方形称为一个部分。

分析

我们先来讨论一般情况。

思考一

对于 \(n\ge3\) 的一般情况,如果要求任意两个大格子到对方的距离最小,怎么做?

根据贪心,我们不难把行走拆为两个部分:

  • 部分一
    从左上角红色格子到绿色格子部分。

  • 部分二
    从绿色格子到右下角红色格子部分。

我们发现,假设如果从任意一个点到另一个点,它的路径是这样的:

每一部分贪心的走。我们发现相邻两个大格子需要走两次,然后分析一下,不难得出距离公式:
\(D(sx,sy,tx,ty)=2\times \max(|sx-sy|,|tx-ty|)\)

思考二

如果起点、终点在小格子里怎么办?

没有关系。我们这些情况转化为大格子的情况。

然后计算权值时再加上蓝色线条部分的长度即可。
这里最多会计算 \(4\times 4=16\) 次。

思考三

如果在起点,终点在同一部分里,怎么办?

对于在大格子,答案显然是 \(0\)

对于小格子,似乎是两点之间的曼哈顿距离?
不对!这就是笔者挂分的点!

它还可以绕出去……具体可以看图。

所以要归并到上面的情况一起计算。

思考四

似乎做完了?
不,还有特殊情况。

  • \(n=1\)

输出曼哈顿距离即可。

  • \(n=2\)

这个改变的地方在这里:

从绿色格子到终点的部分,我们选择直接穿过所有格子。

因为绕两次需要穿过四次格子,直接穿过却只需要三次。
特判一下即可。

至此,这道题就完工了。

Code

#include<bits/stdc++.h>
#define N 600005
#define ll long long
using namespace std;
struct node{
	ll x,y;
};
ll n;
ll sx,sy,tx,ty;
ll d(ll sx,ll sy,ll tx,ll ty)
{
	ll P=max(abs(sx-tx),abs(sy-ty));
	if(n^2) return P*2;
	else return min(abs(sx-tx),abs(sy-ty))*2+(abs(abs(sx-tx)-abs(sy-ty)))/2*3;
}
node B(ll x,ll y)
{
	node tmp;
	tmp.x=x/n;
	tmp.y=y/n;
	return tmp;
}
node S[5],T[5];
ll ds[5],dt[5];
ll sn=1,tn=1;
ll ans=4e18;
ll w[5];
int main()
{
	scanf("%lld",&n);
	scanf("%lld%lld%lld%lld",&sx,&sy,&tx,&ty);
	if(n==1)
	{
		printf("%lld",abs(sx-tx)+abs(sy-ty));
		return 0;
	}
	S[0]=B(sx,sy),T[0]=B(tx,ty);
	if(S[0].x==T[0].x&&S[0].y==T[0].y)
	{
		if((S[0].x&1)==(S[0].y&1)) ans=abs(sx-tx)+abs(sy-ty);
		else
		{
			printf("0");
			return 0;
		}
	}
	if((S[0].x&1)==(S[0].y&1))
	{
		sn=4;
		S[1]=(node){S[0].x-1,S[0].y};ds[1]=abs(S[0].x*n-sx)+1;
		S[2]=(node){S[0].x,S[0].y-1};ds[2]=abs(S[0].y*n-sy)+1;
		S[3]=(node){S[0].x+1,S[0].y};ds[3]=abs(S[0].x*n+n-sx);
		S[4]=(node){S[0].x,S[0].y+1};ds[4]=abs(S[0].y*n+n-sy);
	}
	else S[1]=S[0];
	if((T[0].x&1)==(T[0].y&1))
	{
		tn=4;
		T[1]=(node){T[0].x-1,T[0].y};dt[1]=abs(T[0].x*n-tx)+1;
		T[2]=(node){T[0].x,T[0].y-1};dt[2]=abs(T[0].y*n-ty)+1;
		T[3]=(node){T[0].x+1,T[0].y};dt[3]=abs(T[0].x*n+n-tx);
		T[4]=(node){T[0].x,T[0].y+1};dt[4]=abs(T[0].y*n+n-ty);
	}
	else T[1]=T[0];
	for(int i=1;i<=sn;i++)
	{
		for(int j=1;j<=tn;j++)
		{
			ll dis=d(S[i].x,S[i].y,T[j].x,T[j].y);
			ans=min(ans,dis+ds[i]+dt[j]);
		}
	}
	printf("%lld",ans);
	return 0;
}
posted @ 2024-05-13 09:32  g1ove  阅读(33)  评论(0编辑  收藏  举报