2015期末训练2

poj 8463

典型分治算法。转换坐标和转换方向是等价的。long long用起来要注意,除法可能有点奇怪。算cnt的时候刚开始用了除法,总是不对,改成while循环就好了。四舍五入要用printf。

#include <iostream>
#include <string.h>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
#define ll long long
int map[4][4][2]={{0,0,0,1,1,1,1,0},{0,0,1,0,1,1,0,1},
    {1,1,1,0,0,0,0,1},{1,1,0,1,0,0,1,0}};
int n;
ll p1,p2;
void work(int n,ll p,ll &x,ll &y,int m)//m=0,1,2,3
{
    //cout<<n<<' '<<p<<' '<<x<<' '<<y<<' '<<m<<endl;
    if(n==1)
    {
        x+=map[m][(int)p-1][0];
        y+=map[m][(int)p-1][1];
        return;
    }
    int cnt=0;int t=2*n-2;
    while((p-(1ll<<t))>0){cnt++;p-=(1ll<<t);}
    //cout<<cnt<<endl;
    x+=(map[m][cnt][0]*(1ll<<(n-1)));
    y+=(map[m][cnt][1]*(1ll<<(n-1)));
    if(m==0)
    {
        if(cnt==0)m=1;
        if(cnt==3)m=3;
    }
    else if(m==1)
    {
        if(cnt==0)m=0;
        if(cnt==3)m=2;
    }
    else if(m==2)
    {
        if(cnt==0)m=3;
        if(cnt==3)m=1;
    }
    else if(m==3)
    {
        if(cnt==0)m=2;
        if(cnt==3)m=0;
    }
    work(n-1,p,x,y,m);
}
int main()
{
    int t;cin>>t;
    while(t--)
    {
        cin>>n>>p1>>p2;
        ll X1=0;ll X2=0;
        ll Y1=0;ll Y2=0;
        work(n,p1,X1,Y1,0);
        work(n,p2,X2,Y2,0);
        //cout<<X1<<' '<<X2<<' '<<Y1<<' '<<Y2<<endl;
        printf("%.0lf\n",sqrt((X1-X2)*(X1-X2)*100.0+(Y1-Y2)*(Y1-Y2)*100.0));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yhjpku/article/details/80629109