Problem:
Rubik Dungeon
Problem
あなたは
n
×
n
×
n
の立方体のルービックキューブ型のダンジョンにやってきた。
あなたは現在(
x
1
,
y
1
,
z
1
)の部屋にいる。
目標の宝は(
x
2
,
y
2
,
z
2
)の部屋にある。
あなたは隣接している前後左右上下の部屋に単位時間で移動することができる。
各部屋には6つのボタンがあり、それぞれのボタンを押すことにより、単位時間で、ルービックキューブのように以下の操作を行うことができる：
現在いる部屋と
x
座標の値が同じ全ての部屋を時計または反時計周りに90度回転することができる
現在いる部屋と
y
座標の値が同じ全ての部屋を時計または反時計周りに90度回転することができる
現在いる部屋と
z
座標の値が同じ全ての部屋を時計または反時計周りに90度回転することができる
回転している途中で他の部屋に移動することはできない。
宝のある部屋まで最短で移動した場合の時間を求めよ。
Input
n
x
1
y
1
z
1
x
2
y
2
z
2
入力は全て整数で与えられる。
1行目に
n
が与えられる。
2行目に現在地の座標(
x
1
,
y
1
,
z
1
)、3行目に宝のある部屋の座標(
x
2
,
y
2
,
z
2
)が空白区切りで与えられる。
Constraints
2 ≤ n ≤ 10
5
0 ≤
x
1
,
y
1
,
z
1
,
x
2
,
y
2
,
z
2
≤
n
−1
(
x
1
,
y
1
,
z
1
) ≠ (
x
2
,
y
2
,
z
2
)
Output
最短の時間を出力せよ。
Sample Input 1
3
0 0 0
1 2 2
Sample Output 1
3
Sample Input 2
3
0 0 0
0 0 2
Sample Output 2
2
回転させると宝も移動してしまうので、回転させずに移動する。

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

struct Point{
    int x,y,z;
};

Point READ(){
    int x,y,z;
    cin >>x >>y >>z;
    return {x,y,z};
}

int n;
Point s,g;
int ans;

Point rot_x(Point p){
    return {p.x, n-1-p.z, p.y};
}

Point rot_y(Point p){
    return {p.z, p.y, n-1-p.x};
}

Point rot_z(Point p){
    return {n-1-p.y, p.x, p.z};
}

int dist(Point p, Point q){
    return abs(p.x-q.x) + abs(p.y-q.y) + abs(p.z-q.z);
}

bool IN(Point p){
    return 0<=p.x && p.x<n && 0<=p.y && p.y<n && 0<=p.z && p.z<n;
}

const int dx[6]={1,-1,0,0,0,0};
const int dy[6]={0,0,1,-1,0,0};
const int dz[6]={0,0,0,0,1,-1};
const int add[3]={1,2,1};

void dfs(int d, Point p, int cost){
    ans = min(ans, dist(p,g)+cost);
    if(d==6) return;

    Point np;
    rep(i,6){
        np = p;
        np.x += dx[i];
        np.y += dy[i];
        np.z += dz[i];
        if(IN(np)) dfs(d+1, np, cost+1);
    }

    if(p.x != g.x){
        np = p;
        rep(i,3){
            np = rot_x(np);
            dfs(d+1, np, cost+add[i]);
        }
    }

    if(p.y != g.y){
        np = p;
        rep(i,3){
            np = rot_y(np);
            dfs(d+1, np, cost+add[i]);
        }
    }

    if(p.z != g.z){
        np = p;
        rep(i,3){
            np = rot_z(np);
            dfs(d+1, np, cost+add[i]);
        }
    }
}

int main(){
    cin >>n;
    s = READ();
    g = READ();

    ans = dist(s,g);
    dfs(0,s,0);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3128
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int n;
int ans;
int gx,gy,gz;

void dfs(int c,int x,int y,int z){
	ans=min(ans,abs(x-gx)+abs(y-gy)+abs(z-gz)+c);
	/*if(c<3){
		printf("%d %d %d %d\n",c,x,y,z);
	}
	*/
	if(c==10)return;
	if(z!=gz){
		dfs(c+1,n+1-y,x,z);
		dfs(c+1,y,n+1-x,z);
	}else{
		if(z+1<=n)dfs(c+1,x,y,z+1);
		if(z-1>=1)dfs(c+1,x,y,z-1);
	}
	if(y!=gy){
		dfs(c+1,n+1-z,y,x);
		dfs(c+1,z,y,n+1-x);
	}else{
		if(y+1<=n)dfs(c+1,x,y+1,z);
		if(y-1>=1)dfs(c+1,x,y-1,z);
	}
	if(x!=gx){
		dfs(c+1,x,n+1-z,y);
		dfs(c+1,x,z,n+1-y);
	}else{
		if(x+1<=n)dfs(c+1,x+1,y,z);
		if(x-1>=1)dfs(c+1,x-1,y,z);
	}


}

int main(void){
	int sx,sy,sz;
	scanf("%d",&n);
	scanf("%d%d%d",&sx,&sy,&sz);
	sx++;
	sy++;
	sz++;
	scanf("%d%d%d",&gx,&gy,&gz);
	gx++;
	gy++;
	gz++;
	ans=abs(sx-gx)+abs(gy-sy)+abs(sz-gz);
	dfs(0,sx,sy,sz);
	printf("%d\n",ans);
	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 3212
final_rank: 3

code_snippet: #include <iostream>
#include <tuple>
#include <queue>
#include <map>

using Point = std::tuple<int, int, int>;
using roll_func = Point (*)(const Point &p, int N);

constexpr int INF   = (1 << 29);
constexpr int LIMIT = 10;

Point roll_x(const Point &p, int N)
{
    int x, y, z;
    std::tie(x, y, z) = p;
    return Point{N - y - 1, x, z};
}

Point roll_y(const Point &p, int N)
{
    int x, y, z;
    std::tie(x, y, z) = p;
    return Point{x, N - z - 1, y};
}

Point roll_z(const Point &p, int N)
{
    int x, y, z;
    std::tie(x, y, z) = p;
    return Point{N - z - 1, y, x};
}

Point roll_n(const Point &p, int n, int N, roll_func func)
{
    Point ret = p;
    for (int i = 0; i < n; i++) {
        ret = func(ret, N);
    }
    return ret;
}

Point operator + (const Point &a, const Point &b)
{
    int ax, ay, az, bx, by, bz;

    std::tie(ax, ay, az) = a;
    std::tie(bx, by, bz) = b;

    return Point{ax + bx, ay + by, az + bz};
}

int manhattan_distance(const Point &a, const Point &b)
{
    int ax, ay, az, bx, by, bz;

    std::tie(ax, ay, az) = a;
    std::tie(bx, by, bz) = b;

    return abs(ax - bx) + abs(ay - by) + abs(az - bz);
}

int bfs(int N, const Point &s, const Point &t)
{
    std::queue<Point> Q;
    Q.push(s);

    std::map<Point, int> min_times;
    min_times[s] = 0;

    int ret = INF;
    
    while (!Q.empty()) {
        Point curr = Q.front(); Q.pop();
        int curr_time = min_times[curr];

        ret = std::min(ret, curr_time + manhattan_distance(curr, t));
        
        if (curr_time == LIMIT) {
            continue;
        }

        constexpr Point dp[] = {Point{1, 0, 0}, Point{0, 1, 0}, Point{0, 0, 1}};
        for (int i = 0; i < 3; i++) {
            Point np = curr + dp[i];
            if (min_times.count(np) == 0) {
                min_times[np] = curr_time + 1;
                Q.push(np);
            }
        }
        
        for (int n : {1, 3}) {
            auto get = [](const Point &p, int k) -> int {
                switch (k) {
                    case 0: return std::get<0>(p);
                    case 1: return std::get<1>(p);
                    case 2: return std::get<2>(p);
                }
            };

            int coord = 2;
            for (roll_func func : {roll_x, roll_y, roll_z}) {                
                if (get(curr, coord) !=  get(t, coord)) {
                    Point np = roll_n(curr, n, N, func);
                    if (min_times.count(np) == 0) {
                        min_times[np] = curr_time + 1;
                        Q.push(np);
                    }
                }

                coord = (coord + 1) % 3;
            }
        }
    }

    return ret;
}

int main()
{
    int N;
    int sx, sy, sz, tx, ty, tz;

    std::cin >> N >> sx >> sy >> sz >> tx >> ty >> tz;

    Point s{sx, sy, sz}, t{tx, ty, tz};    
    std::cout << bfs(N, s, t) << std::endl;
    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4168
final_rank: 2

code_snippet: #include <iostream>
#include <algorithm>    
#include <vector>
#include <cassert>
#include <tuple>
using namespace std;

using vi = vector<int>;
using ll = long long;

const ll inf = 1e9;

inline int dist(int x1, int y1, int z1, int x2, int y2, int z2) {
    return abs(x1 - y1) + abs(y1 - y2) + abs(z1 - z2);
}

int dx[] = { 0,0,0,0,-1,1 ,0};
int dy[] = { 0,0,-1,1,0,0 ,0};
int dz[] = { -1,1,0,0,0,0 ,0};

int ans;
int n;

struct P {
    int x, y, z;
    P(int x, int y, int z) :x(x), y(y), z(z) {}
    P() {}
    P rotX(int dir) const {
        return dir ? P(x, n - z - 1, y) : P(x, z, n - y - 1);
    }
    P rotY(int dir) const {
        return dir ? P(z, y, n - x - 1) : P(n - z - 1, y, x);
    }
    P rotZ(int dir) const {
        return dir ? P(n - y-1, x, z) : P(y, n - x-1, z);
    }
    int dist(P const &p) const {
        return abs(x - p.x) + abs(y - p.y) + abs(z - p.z);
    }
    bool inner() const {
        return
            0 <= x && 0 <= y && 0 <= z &&
            x < n && y < n && z < n;
    }
};

void dfs(const P &a, const P &b, int role) {
    // cout << " " << a.x << " " << a.y << " " << a.z << " " << role << endl;
    ans = min(role + a.dist(b), ans);
    if (role == 9) return;
    if (a.x != b.x) {
        dfs(a.rotX(0), b, role + 1);
        dfs(a.rotX(1), b, role + 1);
    }
    if (a.y != b.y) {
        dfs(a.rotY(0), b, role + 1);
        dfs(a.rotY(1), b, role + 1);
    }
    if (a.z != b.z) {
        dfs(a.rotZ(0), b, role + 1);
        dfs(a.rotZ(1), b, role + 1);
    }
}

int main() {
    while (cin >> n) {
        ans = 1e9;
        P a, b;
        cin >> a.x >> a.y >> a.z;
        cin >> b.x >> b.y >> b.z;
        for (int i = 0; i < 6; ++i) {
            P aa = a;
            aa.x += dx[i];
            aa.y += dy[i];
            aa.z += dz[i];
            if (aa.inner()) {
                dfs(aa, b, 0);
            }
        }
        ++ans;
        dfs(a, b, 0);
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 370
memory_kb: 3116
final_rank: 4

code_snippet: #include <iostream>
#include <algorithm>    
#include <vector>
#include <cassert>
#include <tuple>
using namespace std;

using vi = vector<int>;
using ll = long long;

const ll inf = 1e9;

inline int dist(int x1, int y1, int z1, int x2, int y2, int z2) {
    return abs(x1 - y1) + abs(y1 - y2) + abs(z1 - z2);
}

int dx[] = { 0,0,0,0,-1,1 ,0};
int dy[] = { 0,0,-1,1,0,0 ,0};
int dz[] = { -1,1,0,0,0,0 ,0};

int ans;
int n;

struct P {
    int x, y, z;
    P(int x, int y, int z) :x(x), y(y), z(z) {}
    P() {}
    P rotX(int dir) const {
        return dir ? P(x, n - z - 1, y) : P(x, z, n - y - 1);
    }
    P rotY(int dir) const {
        return dir ? P(z, y, n - x - 1) : P(n - z - 1, y, x);
    }
    P rotZ(int dir) const {
        return dir ? P(n - y-1, x, z) : P(y, n - x-1, z);
    }
    int dist(P const &p) const {
        return abs(x - p.x) + abs(y - p.y) + abs(z - p.z);
    }
    bool inner() const {
        return
            0 <= x && 0 <= y && 0 <= z &&
            x < n && y < n && z < n;
    }
};

void dfs(const P &a, const P &b, int role) {
    // cout << " " << a.x << " " << a.y << " " << a.z << " " << role << endl;
    ans = min(role + a.dist(b), ans);
    if (role == 10) return;
    if (a.x != b.x) {
        dfs(a.rotX(0), b, role + 1);
        dfs(a.rotX(1), b, role + 1);
    }
    if (a.y != b.y) {
        dfs(a.rotY(0), b, role + 1);
        dfs(a.rotY(1), b, role + 1);
    }
    if (a.z != b.z) {
        dfs(a.rotZ(0), b, role + 1);
        dfs(a.rotZ(1), b, role + 1);
    }
}

int main() {
    while (cin >> n) {
        ans = 1e9;
        P a, b;
        cin >> a.x >> a.y >> a.z;
        cin >> b.x >> b.y >> b.z;
        if (a.x == b.x || a.y == b.y || a.z == b.z) {
            for (int i = 0; i < 6; ++i) {
                P aa = a;
                aa.x += dx[i];
                aa.y += dy[i];
                aa.z += dz[i];
                if (aa.inner()) {
                    dfs(aa, b, 0);
                }
            }
            ++ans;
        } 
        dfs(a, b, 0);
        cout << ans << endl;
    }
}
accuracy: 0.2571428571428571
time_ms: 320
memory_kb: 3100
final_rank: 5

code_snippet: #include <iostream>
#include <algorithm>    
#include <vector>
#include <cassert>
#include <tuple>
using namespace std;

using vi = vector<int>;
using ll = long long;

const ll inf = 1e9;

inline int dist(int x1, int y1, int z1, int x2, int y2, int z2) {
    return abs(x1 - y1) + abs(y1 - y2) + abs(z1 - z2);
}

int dx[] = { 0,0,0,0,-1,1 ,0};
int dy[] = { 0,0,-1,1,0,0 ,0};
int dz[] = { -1,1,0,0,0,0 ,0};

int ans;
int n;

struct P {
    int x, y, z;
    P(int x, int y, int z) :x(x), y(y), z(z) {}
    P() {}
    P rotX(int dir) const {
        return dir ? P(x, n - z - 1, y) : P(x, z, n - y - 1);
    }
    P rotY(int dir) const {
        return dir ? P(z, y, n - x - 1) : P(n - z - 1, y, x);
    }
    P rotZ(int dir) const {
        return dir ? P(n - y-1, x, z) : P(y, n - x-1, z);
    }
    int dist(P const &p) const {
        return abs(x - p.x) + abs(y - p.y) + abs(z - p.z);
    }
    bool inner() const {
        return
            0 <= x && 0 <= y && 0 <= z &&
            x < n && y < n && z < n;
    }
};

void dfs(const P &a, const P &b, int role) {
    // cout << " " << a.x << " " << a.y << " " << a.z << " " << role << endl;
    ans = min(role + a.dist(b), ans);
    if (role == 10) return;
    if (a.x != b.x) {
        dfs(a.rotX(0), b, role + 1);
        dfs(a.rotX(1), b, role + 1);
    }
    if (a.y != b.y) {
        dfs(a.rotY(0), b, role + 1);
        dfs(a.rotY(1), b, role + 1);
    }
    if (a.z != b.z) {
        dfs(a.rotZ(0), b, role + 1);
        dfs(a.rotZ(1), b, role + 1);
    }
}

int main() {
    while (cin >> n) {
        ans = 1e9;
        P a, b;
        cin >> a.x >> a.y >> a.z;
        cin >> b.x >> b.y >> b.z;
        if (a.x == b.x || a.y == b.y || a.z == b.z) {
            for (int i = 0; i < 6; ++i) {
                P aa = a;
                aa.x += dx[i];
                aa.y += dy[i];
                aa.z += dz[i];
                if (aa.inner()) {
                    dfs(aa, b, 0);
                }
            }
            ++ans;
        } 
        ++ans;
        dfs(a, b, 0);
        cout << ans << endl;
    }
}
accuracy: 0.2571428571428571
time_ms: 320
memory_kb: 3116
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define int long long

typedef long long ll;
typedef pair<int,int>pint;
typedef vector<int>vint;
typedef vector<pint>vpint;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(v) (v).begin(),(v).end()
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
template<class T,class U>void chmin(T &t,U f){if(t>f)t=f;}
template<class T,class U>void chmax(T &t,U f){if(t<f)t=f;}

struct data{
    int x,y,z,xx,yy,zz;
    data(int x,int y,int z,int xx,int yy,int zz):x(x),y(y),z(z),xx(xx),yy(yy),zz(zz){}
    bool operator<(const data &d)const{
        if(x!=d.x)return x<d.x;
        if(y!=d.y)return y<d.y;
        if(z!=d.z)return z<d.z;
        if(xx!=d.xx)return xx<d.xx;
        if(yy!=d.yy)return yy<d.yy;
        return zz<d.zz;
    }
};

int N;
int x,y,z,xx,yy,zz;

map<data,int>dist;
inline void add(data &d,data &nd,queue<data>&que){
    if(dist.find(nd)==dist.end())dist[nd]=1001001001;
    if(dist[nd]>dist[d]+1){
        dist[nd]=dist[d]+1;
        que.push(nd);
    }

}

signed main(){
    cin>>N;
    cin>>x>>y>>z>>xx>>yy>>zz;

    data start(x,y,z,xx,yy,zz);
    dist[start]=0;
    queue<data>que;
    que.push(start);
    while(que.size()){
        data d=que.front();que.pop();
        data nd(0,0,0,0,0,0);
        if(d.x!=d.xx){
            nd=d;
            nd.y=d.z;
            nd.z=N-1-d.y;
            add(d,nd,que);

            nd=d;
            nd.yy=d.zz;
            nd.zz=N-1-d.yy;
            add(d,nd,que);
        }
        if(d.y!=d.yy){
            nd=d;
            nd.x=d.z;
            nd.z=N-1-d.x;
            add(d,nd,que);

            nd=d;
            nd.xx=d.zz;
            nd.zz=N-1-d.xx;
            add(d,nd,que);
        }
        if(d.z!=d.zz){
            nd=d;
            nd.x=d.y;
            nd.y=N-1-d.z;
            add(d,nd,que);

            nd=d;
            nd.xx=d.yy;
            nd.yy=N-1-d.zz;
            add(d,nd,que);
        }
    }

    int mi=1001001001;
    each(it,dist){
        data d=it->fi;
        int cost=abs(d.x-d.xx)+abs(d.y-d.yy)+abs(d.z-d.zz);
        chmin(mi,cost+it->se);
    }
    cout<<mi<<endl;
    return 0;
}
accuracy: 0.22857142857142856
time_ms: 10
memory_kb: 1540
final_rank: 7