【SHNU_RUSHer】【SHNU Winter Camp】day2 - D - Fractal Streets [ POJ_3889 ]

26 篇文章 1 订阅
26 篇文章 0 订阅

Fractal Streets

[by_041]

题目链接_POJ

题目理解

  • 本题是和希尔伯特曲线有关的一道规律题(因为存在重复单元)

  • 原来的基础方向是这样]的,我们可以将其划分为四个部分 ① ∣ ② ④ ∣ ③ \frac{①|②}{④|③} ,根据题意在②③部分中的细分单位结构和原来的整体方向相同,而在①处位置的细分方向沿主对角线方向翻转,④处沿右对角线翻转,所以有翻转状态st1,st2表示的细分单位结构,见下表:

在这里插入图片描述

  • 所以我们可以从二进制的高位 2 2 n − 1 2^{2n-1} 22n1 2 2 n − 1 2^{2n-1} 22n1开始每俩位截取一次,用得到的状态更新细分结构的方向即位置,已 n = 2 n=2 n=2为例,可以看到二进制下房子编号的规律:

在这里插入图片描述

  • 综上,我们可以得到本体的具体思路:

    • 每两位地取二进制定位下一层细分结构位置
    • 移动当前表示位置坐标的二进制数,生成相应的下层位置
    • 按照规则翻转当前状态得到下一层的结构方向
  • 还要注意数据大小需要用到long longdouble,输出格式一定要用printf%.0lf关键格式,不然会WA(cout宣布破产!)!!!

  • AC代码如下:

#include<iostream>
#include<cmath>


using namespace std;


long long pow4[41];


void guai(long long n,long long s,long long &x,long long &y)
{
    if(n==1)
    {
        if(s==1)
        {
            x=1;
            y=1;
        }
        else
        if(s==2)
        {
            x=1;
            y=2;
        }
        else
        if(s==4)
        {
            x=2;
            y=1;
        }
        else
        {
            x=2;
            y=2;
        }
        return;
    }
    if(s<=pow4[n-1])
    {
        guai(n-1,s,y,x);
    }
    else if(s<=2*pow4[n-1])
        {
            guai(n-1,s-pow4[n-1],x,y);
            y+=(1<<(n-1));
        }
        else if(s<=3*pow4[n-1])
            {
                guai(n-1,s-2*pow4[n-1],x,y);
                x+=(1<<(n-1));
                y+=(1<<(n-1));
            }
            else
            {
                guai(n-1,s-3*pow4[n-1],y,x);
                x=(1<<n)+1-x;
                y=(1<<(n-1))+1-y;
            }
}
int main()
{
    pow4[1]=4;
    for(int i=2;i<=33;i++)
    {
        pow4[i]=4*pow4[i-1];
    }
    int T;
    scanf("%d",&T);
    while(T--)
    {
        long long s,e,n,sx,sy,ex,ey;
        scanf("%lld%lld%lld",&n,&s,&e);
        guai(n,s,sx,sy);
        guai(n,e,ex,ey);
        printf("%.0f\n",sqrt(((double)sx-(double)ex)*((double)sx-(double)ex)+((double)sy-(double)ey)*((double)sy-(double)ey))*10);
    }
	return 0;
}


  • 原来废掉但是思路正确的枚举情况の代码(可便于理解🤔and有纪念价值😜):
#include<stdio.h>
#include<iostream>
#include<bitset>
#include<cmath>

using namespace std;


// bitset<101>u,v;
bool st1,st2,u[1001],v[1001];
//st1表示主对角线上的翻转情况,st2表示副对角线上的翻转情况
long long n,val,ux,uy,vx,vy;

int main()
{
//cout<<(unsigned long long)(1.6+0.5)<<endl;
// freopen(".out","w",stdout);

	int T;
	scanf("%d",&T);
	while(T--)
	{
		cin>>n>>val;
		val--;
		// u=val;
		// cout<<u<<endl;
		// u=0;
		int bs_f=0;
		while(val)
		{
			u[bs_f++]=val%2;
			val/=2;
		}
		// cout<<u;
		cin>>val;
		// v=val-1;
		// cout<<u<<endl<<v<<endl;

		st1=st2=false;
		ux=uy=vx=vy=0;
		long long nn=n;
		while(n--)
		{
			//	u[(n<<1)+1]	u[n<<1]	st1	st2
			ux<<=1;
			uy<<=1;
			if(u[(n<<1)+1]==0&&u[n<<1]==0&&st1==0&&st2==0)
			{
				st1=1;
				continue;
			}
			if(u[(n<<1)+1]==0&&u[n<<1]==1&&st1==0&&st2==0)
			{
				uy++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==0&&st1==0&&st2==0)
			{
				uy++;
				ux++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==1&&st1==0&&st2==0)
			{
				ux++;
				st2=1;
				continue;
			}
			///
			if(u[(n<<1)+1]==0&&u[n<<1]==0&&st1==1&&st2==0)
			{
				st1=0;
				continue;
			}
			if(u[(n<<1)+1]==0&&u[n<<1]==1&&st1==1&&st2==0)
			{
				ux++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==0&&st1==1&&st2==0)
			{
				uy++;
				ux++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==1&&st1==1&&st2==0)
			{
				uy++;
				st2=0;
				continue;
			}
			///
			if(u[(n<<1)+1]==0&&u[n<<1]==0&&st1==0&&st2==1)
			{
				ux++;uy++;st1=1;
				continue;
			}
			if(u[(n<<1)+1]==0&&u[n<<1]==1&&st1==0&&st2==1)
			{
				uy++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==0&&st1==0&&st2==1)
			{
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==1&&st1==0&&st2==1)
			{
				ux++;st2=0;
				continue;
			}
			///
			if(u[(n<<1)+1]==0&&u[n<<1]==0&&st1==1&&st2==1)
			{
				ux++;uy++;st1=0;
				continue;
			}
			if(u[(n<<1)+1]==0&&u[n<<1]==1&&st1==1&&st2==1)
			{
				ux++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==0&&st1==1&&st2==1)
			{
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==1&&st1==1&&st2==1)
			{
				uy++;st2=0;
				continue;
			}
		}
		vx=ux;
		vy=uy;
		ux=uy=st1=st2=0;
		// u=val-1;
		val--;bs_f=0;
		for(int iiii=0;iiii<=100;iiii++)
			u[iiii]=0;
		while(val)
		{
			u[bs_f++]=val%2;
			val/=2;
		}
		n=nn;
		while(n--)
		{
			//	u[(n<<1)+1]	u[n<<1]	st1	st2
			ux<<=1;
			uy<<=1;
			if(u[(n<<1)+1]==0&&u[n<<1]==0&&st1==0&&st2==0)
			{
				st1=1;
				continue;
			}
			if(u[(n<<1)+1]==0&&u[n<<1]==1&&st1==0&&st2==0)
			{
				uy++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==0&&st1==0&&st2==0)
			{
				uy++;
				ux++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==1&&st1==0&&st2==0)
			{
				ux++;
				st2=1;
				continue;
			}
			///
			if(u[(n<<1)+1]==0&&u[n<<1]==0&&st1==1&&st2==0)
			{
				st1=0;
				continue;
			}
			if(u[(n<<1)+1]==0&&u[n<<1]==1&&st1==1&&st2==0)
			{
				ux++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==0&&st1==1&&st2==0)
			{
				uy++;
				ux++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==1&&st1==1&&st2==0)
			{
				uy++;
				st2=0;
				continue;
			}
			///
			if(u[(n<<1)+1]==0&&u[n<<1]==0&&st1==0&&st2==1)
			{
				ux++;uy++;st1=1;
				continue;
			}
			if(u[(n<<1)+1]==0&&u[n<<1]==1&&st1==0&&st2==1)
			{
				uy++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==0&&st1==0&&st2==1)
			{
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==1&&st1==0&&st2==1)
			{
				ux++;st2=0;
				continue;
			}
			///
			if(u[(n<<1)+1]==0&&u[n<<1]==0&&st1==1&&st2==1)
			{
				ux++;uy++;st1=0;
				continue;
			}
			if(u[(n<<1)+1]==0&&u[n<<1]==1&&st1==1&&st2==1)
			{
				ux++;
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==0&&st1==1&&st2==1)
			{
				continue;
			}
			if(u[(n<<1)+1]==1&&u[n<<1]==1&&st1==1&&st2==1)
			{
				uy++;st2=0;
				continue;
			}
		}
		// cout<<ux<<" "<<uy<<" - "<<vx<<" "<<vy<<endl;
		long long a_x1=ux,a_y1=uy,a_x2=vx,a_y2=vy;
		// cout<<(long long)(sqrt(((a_x1-a_x2)*(a_x1-a_x2)+(a_y1-a_y2)*(a_y1-a_y2)))*10+0.5)<<endl;
		printf("%.0lf\n",(sqrt((((double)a_x1-(double)a_x2)*((double)a_x1-(double)a_x2)+((double)a_y1-(double)a_y2)*((double)a_y1-(double)a_y2)))*10));
	}
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值