正题
题目链接:http://poj.org/problem?id=3889
大意
第一级城市为图一,然后每次扩展一级就将原本的城市复制3份,一份放上面,一份正旋90’放左上,一份逆序90’放左边,最后将4份的头和尾连起来,规定左上角为编号1,之后根据道路编号。
求在一个n级城市中s号和d号的直线距离。
解题思路
我们可以从n级逐一降级下去,然后每次旋转的话我们可以旋转得出的坐标。
code
#include<cstdio>
#include<algorithm>
#include<cmath>
#define ps(x) x*x
using namespace std;
int pows[31],n,s,d,t,x,y,x1,yy1,x2,y2;
void getid(int n,int num)//求坐标
{if(n==1){switch(num){case 2:{y+=1;break;}case 3:{x+=1;y+=1;break;}case 4:{x+=1;break;}}return;}//最后一级特殊判断int w=(num-1)/pows[n-1]/pows[n-1];//判断是在哪个区块switch(w){case 0:{getid(n-1,num-(pows[n-1]*pows[n-1])*w);swap(x,y);//旋转坐标break;}case 1:{getid(n-1,num-(pows[n-1]*pows[n-1])*w);y+=pows[n-1];//旋转坐标break;}case 2:{getid(n-1,num-(pows[n-1]*pows[n-1])*w);x+=pows[n-1];y+=pows[n-1];//旋转坐标break;}case 3:{getid(n-1,num-(pows[n-1]*pows[n-1])*w);int dx=x,dy=y;x=pows[n]+1-dy;y=pows[n-1]+1-dx;//旋转坐标break;}}
}
double dis(double x1,double yy1,double x2,double y2)
{return sqrt(ps(fabs(x1-x2))+ps(fabs(yy1-y2)));
}
int main()
{scanf("%d",&t);pows[0]=1;for(int i=1;i<=30;i++)pows[i]=pows[i-1]*2;x=1;y=1;for(int ti=1;ti<=t;ti++){scanf("%d%d%d",&n,&s,&d);getid(n,s);x1=x*10;yy1=y*10;x=1;y=1;getid(n,d);x2=x*10;y2=y*10;x=1;y=1;printf("%0.lf\n",dis(x1,yy1,x2,y2));//求直线距离}
}