Fractal Streets (POJ3889)(分形图、递归)

题目传送门:http://poj.org/problem?id=3889
感谢大雪菜大神bilibili上的讲解和李煜东大神书本的引导。
题面大概意思是:
   给你一个原始的分形图,t组数据,对于每组数据,输入3个数n,h,o (n为在第n级,h,o为两个房子的编号),求在第n级情况下,编号为h和o的两个点之间的距离*10为多少。
  其中,第n级分形图形成规则如下:

  1. 首先先在右下角和右上角复制一遍n-1情况下的分形图
  2. 然后将n-1情况下的分形图顺时针旋转90度,放到左上角
  3. 最后将n-1情况下的分形图逆时针旋转90度 ,放到左下角
    编号是从左上角那个点开始计1,沿着道路计数。
    在这里插入图片描述分析:
    这是著名的通过一定规律无限包含自身的分形图。为了计算方便,我们将题目中房屋编号从0开始编号,那么S与D也都减掉1.
    大体思路:设calc(n,m)求编号为m的房屋编号在n级城市中的坐标位置,那么距离是:calc(n,s-1) 与 calc(n,d-1)的距离。
    从n(n > 1)级城市由四座n-1级城市组成,其中:
      1.左上的n-1级城市由城市结构顺时针旋转90度,从编号的顺序看,该结构还做水平翻转,坐标转换至n级时如下图。
      2与3.右上和右下和原始城市结构一样,坐标转换至n级时如下图。
      在这里插入图片描述  4.左下的n-1级城市由城市结构逆时针旋转90度,从编号的顺序看,该结构也做了水平翻转。
     
      旋转坐标的变化可通过公式:
     在这里插入图片描述在这里插入图片描述
      (设len = 2(n-1))当旋转角度是逆时针90度时,也就是顺时针270度时,(x,y)->(y, -x),然后再进行水平翻转,(y,-x)->(-y,-x)。然后再将图形平移到n级图形的左下角,在格子上的坐标变化是,水平方向增加len - 1个位置,垂直方向增加2len - 1个位置。因此坐标(x,y)按照规则转移到了(2len-1-y,len-1-x).
      注意:n-1级格子里拥有的房子数量是cnt = 22n /4,即22n-2.
        当前编号m在N级格子的哪个方位是:m / cnt.
        当前编号m在n-1级格子里的编号是: m %cnt;
    详细代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
pair<LL,LL> calc(LL n, LL m){
	if(n == 0) return make_pair(0,0);
	LL len = 1ll << (n-1) , cnt = 1ll << (2*n - 2);
	pair<LL,LL> pos = calc( n-1, m%cnt);
	LL x = pos.first , y = pos.second;
	LL z = m / cnt;//z的值代表这n-1级的(x,y)在n级城市中的方位。
	if ( z == 0 ) return make_pair(y , x); //左上 
	if ( z == 1 ) return make_pair(x, y + len);//右上 
	if ( z == 2 ) return make_pair(x+len, y + len);//右下 
	return make_pair(2*len-1-y, len - 1- x);// 左下 
}
int main(){
	int T;
	cin >> T;
	while(T--){
		LL N,A,B;
		cin >> N >> A >> B;
		pair<LL,LL> s = calc(N, A - 1);
		pair<LL,LL> d = calc(N, B - 1);
		LL ax = s.first - d.first,ay = s.second - d.second;
		cout <<fixed << setprecision(0) << sqrt(ax * ax + ay * ay)*10<< endl;
	} 
	return 0;
}
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值