Atcoder Panasonic Programming Contest 2020 F Fractal Shortest Path 分而治之+挤压行的空间

Panasonic Programming Contest 2020   比赛人数6617   慢,比赛开始后10分钟才看到题目,比赛题目比ABC要灵活些

Atcoder Panasonic Programming Contest 2020 F Fractal Shortest Path 分而治之+挤压行的空间

总目录详见https://blog.csdn.net/mrcrack/article/details/104454762

在线测评地址https://atcoder.jp/contests/panasonic2020/tasks/panasonic2020_f

思路同https://www.cnblogs.com/zdragon1104/p/12496988.html

题解:将图分为9块,其中123为一层,456为一层,789为一层。

1.两点在不同层(除了2,8):两点之间的距离即为两点曼哈顿距离,

为了避免(2,8)这种情况,可以通过交换(x,y)转化为(4,6)。

下图中(0,3)->(3,0),(8,5)->(5,8)

2.两点在同一层,并且不在456这层:可以往下递归,y轴保持不变。

3.两点在同一层,并且在456这层:由于需要绕过中间这块,只要判断往左走还是往右走即可。

向左走,走过的距离abs(y1-y2)+(x1%w+1+x2%w+1)由来,详见下图

向右走,走过的距离abs(y1-y2)+(w-x1%w)+(w-x2%w)由来,详见下图

在向左走,向右走,路径中,取最小值。

AC代码如下

#include <cstdio>
#include <algorithm>
#define LL long long
using namespace std;
LL width[35];
LL cal(LL x1,LL y1,LL x2,LL y2,int level){
	LL w;
	if(level==0)return abs(y1-y2);//路径上一直未遇到黑色方块
	w=width[level-1];//当前级别level,深入到9个level-1级别中进行处理
	if(x1/w!=x2/w)return abs(x1-x2)+abs(y1-y2);//处在不同层中,可用曼哈顿距离处理
	if(x1/w==1&&abs(y1/w-y2/w)>=2)//x1/w==x2/w  处于同一层,且在456这一层
		return abs(y1-y2)+min(x1%w+1+x2%w+1,(w-x1%w)+(w-x2%w));//x1%w+1+x2%w+1向左推进,(w-x1%w)+(w-x2%w)向右推进
	return cal(x1%w,y1,x2%w,y2,level-1);//当前处理不了,只能深入到level-级别中进行处理,固定abs(y1-y2),针对x进行处理,因x1/w==x2/w,故可取模
}
int main(){
	int i,q;
	width[0]=1;
	for(i=1;i<=29;i++)width[i]=width[i-1]*3;
	LL x1,y1,x2,y2;
	scanf("%d",&q);
	while(q--){
		scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
		x1--,y1--,x2--,y2--;//涉及取模运算,故第1行变成第0行,故第1列变成第0列
		if(abs(x1-x2)>abs(y1-y2))swap(x1,y1),swap(x2,y2);//抓住图形具有对称性,避免出现258的情况。
		printf("%lld\n",cal(x1,y1,x2,y2,30));
	}
	return 0;
}
发布了620 篇原创文章 · 获赞 550 · 访问量 46万+

猜你喜欢

转载自blog.csdn.net/mrcrack/article/details/104938129
今日推荐