求解皮亚诺曲线距离
【问题描述】
皮亚诺曲线是一条平面内的曲线。
下图给出了皮亚诺曲线的 1 阶情形,它是从左下角出发,经过一个 3 × 3 的方格中的每一个格子,最终到达右上角的一条曲线。
下图给出了皮亚诺曲线的 2 阶情形,它是经过一个 32 × 32 的方格中的每一个格子的一条曲线。它是将 1 阶曲线的每个方格由 1 阶曲线替换而成。
下图给出了皮亚诺曲线的 3 阶情形,它是经过一个 33 × 33 的方格中的每一个格子的一条曲线。它是将 2 阶曲线的每个方格由 1 阶曲线替换而成。
皮亚诺曲线总是从左下角开始出发,最终到达右上角。
我们将这些格子放到坐标系中,对于 k 阶皮亚诺曲线,左下角的坐标是(0, 0),右上角坐标是 (3k − 1, 3k − 1),右下角坐标是 (3k − 1, 0),左上角坐标是(0, 3k − 1)。
给定 k 阶皮亚诺曲线上的两个点的坐标,请问这两个点之间,如果沿着皮亚诺曲线走,距离是多少?
【输入格式】
输入的第一行包含一个正整数 k,皮亚诺曲线的阶数。第二行包含两个整数 x1, y1,表示第一个点的坐标。
第三行包含两个整数 x2, y2,表示第二个点的坐标。
【输出格式】
输出一个整数,表示给定的两个点之间的距离。
【样例输入】
1
0 0
2 2
【样例输出】
8
【样例输入】
2
0 2
0 3
【样例输出】
13
【评测用例规模与约定】
对于 30% 的评测用例,0 ≤ k ≤ 10。
对于 50% 的评测用例,0 ≤ k ≤ 20。
对于所有评测用例,0≤k≤100, 0≤x1,y1,x2,y2<3^k, x1,y1,x2,y2≤10^18。
数据保证答案不超过 10^18。
【思路】
先计算每个点到左下角点的距离,接着相减;
用分治法,将高阶的皮亚诺曲线分割成低一阶的皮亚诺曲线,需要确定终点在哪块区域,还要确定下起点的位置,每次dfs需要对起点变换下位置。
【代码】
思路有,但是代码不太好写,隔了几天在看的时候,重写做了下,然后解决。
注意下long long类型可能会溢出,需要无符号long long
#include<iostream>
#define endl '\n'
#define maxn 100+5
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int n=2;
ull x1=0,y1=0;
ull x2=2,y2=2;
//获取一阶曲线距离
int get_dis(const ull x, const ull y, int dir){
if(dir==1){ //左下角为起点
if(x==0) return y;
else if(x==1) return 5-y;
else return 6+y;
}else if(dir==2){ //右上角为起点
if(x==0) return 8-y;
else if(x==1) return 3+y;
else return 2-y;
}else if(dir==3){ //右下角为起点
if(x==0) return 6+y;
else if(x==1) return 5-y;
else return y;
}else if(dir==4){ //左上角为起点
if(x==0) return 2-y;
else if(x==1) return 3+y;
else return 8-y;
}
}
//len为边长,dir设定起点位置,(x,y)确定终点坐标
ull dfs(ull x,ull y,ull len, int dir){
if(len==3) return get_dis(x,y,dir);
//根据dir变换起点和点坐标
if(dir==2){
x=len-1-x;
y=len-1-y;
}else if(dir==3){
x=len-1-x;
}else if(dir==4){
y=len-1-y;
}
//左下角为起点
int nxd;
ull nxl=len/3, dis;
ull mx=x%nxl, my=y%nxl, dx=x/nxl, dy=y/nxl;
if(dx==0){
dis=dy*nxl*nxl;
if(dy==0) nxd=1;
else if(dy==1) nxd=3;
else nxd=1;
}else if(dx==1){
dis=(5-dy)*nxl*nxl;
if(dy==0) nxd=4;
else if(dy==1) nxd=2;
else nxd=4;
}else{
dis=(6+dy)*nxl*nxl;
if(dy==0) nxd=1;
else if(dy==1) nxd=3;
else nxd=1;
}
return dis+dfs(mx, my, nxl, nxd);
}
int main(){
cin>>n;
cin>>x1>>y1;
cin>>x2>>y2;
ull len=1;
for(int i=0;i<n;i++) len*=3;
// cout<<len<<endl;
ull dis1=dfs(x1,y1,len,1);
ull dis2=dfs(x2,y2,len,1);
ull ans=dis2-dis1;
// cout<<dis1<<" "<<dis2<<" "<<ans<<endl;
cout<<ans<<endl;
return 0;
}
2021-5-3 感谢观看-