Openjudge 8463 Stupid cat & doge

Stupid cat & doge

链接

典型的分治

找遍了所有搜索引擎居然没有此题的题解 

那我发一个好了

如何分治

此题考虑当前等级和上一等级的关系 

例如 右上的部分和右下的部分和上一部分一样

而左上和左下是顺时针旋转和逆时针旋转 

根据此关系来推导出坐标的变换即可

注释很详细不多解释

#include <cmath>
#include <iostream>

#define LL long long int

using namespace std;

int base_x[5]={0,1,1,2,2};//第一等级为基底 
int base_y[5]={0,1,2,2,1};//任何等级都由第一等级推过去 

long long int k,a,b,t;

LL search_y(LL k,LL n);//声明函数 

double dis(LL x1,LL y1,LL x2,LL y2){return sqrt(pow(x1-x2,2)+pow(y1-y2,2))*10;}
//计算距离函数 
LL search_x(LL k,LL n)
{
	if(k==1)return base_x[n];//边界 如果是第一等级 直接返回答案 即该标号横坐标 
	else{
		LL map=pow(2,k<<1);//地图的大小 即k等级的动物园共有几个房屋 
		int block=(n%(map>>2)==0)?(n/(map>>2)):(n/(map>>2))+1;
		//计算标号为n的房屋在地图的哪一个方位(左上右上左下右下)特殊条件特殊判断 
		if(block==1)return search_y(k-1,n);//分类搜索答案 
		//如果是第一块 旋转后横坐标变成纵坐标 
		else if(block==2)return search_x(k-1,(n%(map>>2)==0)?n/2:n%(map>>2));
		//如果是第二块 形状和上一等级一样无需变化 只是求出上一等级的横坐标即可 
		else if(block==3)return search_x(k-1,n%(map>>1))+pow(2,k-1);
		//如果是第三块 形状也一样 求出上一等级横坐标还要加上半个边长 
		else if(block==4)return pow(2,k)+1-search_y(k-1,n%(map*3/4));
		//如果是第四块 逆时针旋转 先顺时针旋转再中心对称 
	}
}
/*注释同上*/
LL search_y(LL k,LL n)
{
	if(k==1)return base_y[n];
	else{
		LL map=pow(2,k<<1);
		int block=(n%(map>>2)==0)?(n/(map>>2)):(n/(map>>2))+1;
		if(block==1)return search_x(k-1,n);
		else if(block==2)return search_y(k-1,(n%(map>>2)==0)?n/2:n%(map>>2))+pow(2,k-1);
		else if(block==3)return search_y(k-1,n%(map>>1))+pow(2,k-1);
		else if(block==4)return pow(2,k-1)+1-search_x(k-1,n%(map*3/4));
	}
}
/*注释同上*/
int main()
{
	cin>>t;//数据总量 
	while(t--){
		
		cin>>k>>a>>b;//读入等级数 StupidCat和Doge的房屋编号 
		
		LL x1=search_x(k,a);//求出Cat的房屋横坐标 
		LL y1=search_y(k,a);//求出Cat的房屋纵坐标 
		LL x2=search_x(k,b);//求出Doge的房屋横坐标 
		LL y2=search_y(k,b);//求出Doge的房屋纵坐标
		
		double ans=dis(x1,y1,x2,y2);//计算两者之间的距离 
		
		LL temp=ans;//以下是四舍五入计算 
		cout<<((ans>=temp+0.5)?(temp+1):temp)<<endl;
	}
}

End。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值