Problem:
Billiards Sorting
Rotation is one of  several popular pocket billiards games.
It uses 15 balls numbered from 1 to 15, and set  them up  as illustrated in the following figure  at the beginning of a game.
(Note:  the ball order  is  modified from  real-world Rotation rules for simplicity of the problem.)
[ 1]
      [ 2][ 3]
    [ 4][ 5][ 6]
  [ 7][ 8][ 9][10]
[11][12][13][14][15]
You are an engineer  developing an automatic billiards machine.
For the first step you  had to  build a machine that sets up the initial condition.
This project  went well, and finally  made up a machine that  could arrange the balls in the triangular shape.
However, unfortunately, it  could not place the balls in the correct order.
So now you are trying to  build another machine that fixes the order of balls by swapping   them.
To cut off the cost, it is only allowed to swap the ball #1 with its neighboring balls that are  not  in the same  row.
For example, in the  case below,  only the following pairs can be swapped: (1,2), (1,3), (1,8), and (1,9).
[ 5]
      [ 2][ 3]
    [ 4][ 1][ 6]
  [ 7][ 8][ 9][10]
[11][12][13][14][15]
Write a program that calculates the minimum number of swaps required.
Input
The first line of each test case has an integer
N
(
1 \leq N \leq 5
), which is  the number of the rows.
The following
N
lines describe how the balls are arranged by the first machine;
the
i
-th of them consists of exactly
i
integers, which are the ball numbers.
The input terminates when
N
= 0. Your program must not output for this case.
Output
For each test case, print its case number and the minimum number of swaps.
You can assume that any arrangement can be fixed by not more than 45 swaps.
Sample Input
2
3
2 1
4
9
2 4
8 5 3
7 1 6 10
0
Output for the Sample Input
Case 1: 1
Case 2: 13

Submitted solutions:

code_snippet: #include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <cstdlib>
#define INF 0x3f3f3f3f
#define er(i) (1<<i)
#define lb lower_bound
#define up upper_bound
#define eps 1e-8
#define mp make_pair
#define pii pair<int, int>
#define zero(x) (((x)>0?(x):-(x))<eps)
#define mem(a,b) memset((a),(b),sizeof((a)))
#define lld long long

using namespace std;
int dir[20][4];
int dis[20][20];
int n;
int a[20];
int b[20];
int ans;

int cal() {
    int sum = 0;
    int i;
    for(i = 1; i <= n; i++)
        if (a[i] != 1)
            sum += dis[i][a[i]];
    return sum;
}

int dfs(int dep, int now, int pre) {
    int i;
//      cout<<dep<<endl;
//      for(i = 1; i <= n; i++)
//      cout<<a[i]<<"  ";
//      cout<<endl;
//      cout<<cal()<<endl;
    int s = cal();
    if (s == 0) return 1;
    if (dep + s > ans) return 0;

    for(i = 3; i >= 0; i--) {
        int u = dir[now][i];
        if (u == 0 || u > n || u == pre) continue;
       swap(a[now], a[u]);
        if (dfs(dep + 1, u, now)) return 1;
        swap(a[now], a[u]);
    }
    return 0;
}

int main() {
    int cas = 0;
    int i, j, k;
    mem(dir,0);
    dir[1][0] = 2;
    dir[1][1] = 3;
    dir[2][0] = 1;
    dir[2][1] = 4;
    dir[2][3] = 5;
    dir[3][0] = 1;
    dir[3][1] = 5;
    dir[3][2] = 6;
    dir[4][0] = 2;
    dir[4][1] = 7;
    dir[4][2] = 8;
    dir[5][0] = 2;
    dir[5][1] = 3;
    dir[5][2] = 8;
    dir[5][3] = 9;
    dir[6][0] = 3;
    dir[6][1] = 9;
    dir[6][2] = 10;
    dir[7][0] = 4;
    dir[7][1] = 11;
    dir[7][2] = 12;
    dir[8][0] = 4;
    dir[8][1] = 5;
    dir[8][2] = 12;
    dir[8][3] = 13;
    dir[9][0] = 5;
    dir[9][1] = 6;
    dir[9][2] = 13;
    dir[9][3] = 14;
    dir[10][0] = 6;
    dir[10][1] = 14;
    dir[10][2] = 15;
    dir[11][0] = 7;
    dir[12][0] = 7;
    dir[12][1] = 8;
    dir[13][0] = 8;
    dir[13][1] = 9;
    dir[14][0] = 9;
    dir[14][1] = 10;
    dir[15][0] = 10;
    mem(dis,63);
    for(i = 1; i <= 15; i++) {
        dis[i][i] = 0;
        for(j = 0; j < 4; j++) {
            if (dir[i][j] == 0) continue;
            dis[i][dir[i][j]] = 1;
        }
    }
    for(k = 1; k <= 15; k++)
        for(i = 1; i <= 15; i++)
            for(j = 1; j <= 15; j++)
                if (i != j && j != k && i != k)
                if (dis[i][k] + dis[k][j] < dis[i][j])
                    dis[i][j] = dis[i][k] + dis[k][j];
//    for(i = 1; i <= 10; i++)
//    for(j = 1; j <= 10; j++)
//    cout<<i<<"  "<<j<<"  "<<dis[i][j]<<endl;
    while(~scanf("%d", &n), n) {
        n = n * (n + 1) / 2;
        int p = 0;
        for(i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        for(i = 1; i <= n; i++)
            if (a[i] == 1) p = i;
        for(i = 1; i <= n; i++)
            b[i] = a[i];
        int st = 0;
        if (p == 1 || (p >= 4 && p <= 6) || (p >= 11 && p <= 15)) st = 0; else st = 1;
        for(ans = st; ans <= 45; ans+=2) {
//            for(i = 1; i <= n; i++)
//                a[i] = b[i];
            if (dfs(0, p, -1) != 0) break;
        }
        printf("Case %d: %d\n", ++cas, ans);
    }
    return 0;
}
accuracy: 1
time_ms: 4640
memory_kb: 3572
final_rank: 1

code_snippet: #include<cstdio>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

typedef long long ll;

//        0
//      1  2
//     3  4  5
//   6  7  8  9
// 10 11 12 13 14

// nei[i] := ( マス i と隣接するマス )
const int nei[15][4]={
	{ 1, 2,-1,-1},
	{ 0, 3, 4,-1},
	{ 0, 4, 5,-1},
	{ 1, 6, 7,-1},
	{ 1, 2, 7, 8},
	{ 2, 8, 9,-1},
	{ 3,10,11,-1},
	{ 3, 4,11,12},
	{ 4, 5,12,13},
	{ 5,13,14,-1},
	{ 6,-1,-1,-1},
	{ 6, 7,-1,-1},
	{ 7, 8,-1,-1},
	{ 8, 9,-1,-1},
	{ 9,-1,-1,-1}
};

int dist[15][15]; // dist[i][j] := ( マス i にある数字をマス j に移動するための最短手数 )

int n,a[15];

int hstar(int now){
	int sum=0;
	rep(i,n) if(a[i]!=0) sum+=dist[a[i]][i];
	return now+sum;
}

int ub;
bool dfs(int now,int p,int pre,int end){
	if(end==n) return true;

	if(hstar(now)>ub) return false;

	// rep(k,4){
	for(int k=3;k>=0;k--){ // 逆順に調べた方が 10 秒くらい速い ( テストケースの特性?? )
		int q=nei[p][k];
		if(q==-1 || q>=n || q==pre) continue; // 直前の状態には遷移しない
		swap(a[p],a[q]);
		int end2=end-(a[q]==p?1:0)-(a[p]==q?1:0)+(a[p]==p?1:0)+(a[q]==q?1:0);
		if(dfs(now+1,q,p,end2)) return true;
		swap(a[p],a[q]);
	}
	return false;
}

int main(){
	rep(i0,15){
		rep(i,15) dist[i0][i]=77;
		dist[i0][i0]=0;
		int Q[32],head=0,tail=0; Q[tail++]=i0;
		while(head<tail){
			int i=Q[head++];
			rep(k,4){
				int j=nei[i][k];
				if(j!=-1 && dist[i0][j]==77) dist[i0][j]=dist[i0][i]+1, Q[tail++]=j;
			}
		}
	}

	for(int cas=1;scanf("%d",&n),n;cas++){
		n=n*(n+1)/2;
		rep(i,n) scanf("%d",a+i), a[i]--;

		int end=0; // 揃っている数字の個数
		rep(i,n) if(a[i]==i) end++;

		int p=find(a,a+15,0)-a;
		int h=(1<=p&&p<=2||6<=p&&p<=9?1:0); // 1 のある行 mod 2
		for(ub=h;ub<45;ub+=2) if(dfs(0,p,-1,end)) break;
		printf("Case %d: %d\n",cas,ub);
	}

	return 0;
}
accuracy: 1
time_ms: 5980
memory_kb: 1028
final_rank: 5

code_snippet: #include<cstdio>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

typedef long long ll;

//        0
//      1  2
//     3  4  5
//   6  7  8  9
// 10 11 12 13 14

// nei[i] := ( テ」ツδ榲」ツつケ i テ」ツ?ィテゥツ堋」テヲツ篠・テ」ツ?凖」ツつ凝」ツδ榲」ツつケ )
const int nei[15][4]={
	{ 1, 2,-1,-1},
	{ 0, 3, 4,-1},
	{ 0, 4, 5,-1},
	{ 1, 6, 7,-1},
	{ 1, 2, 7, 8},
	{ 2, 8, 9,-1},
	{ 3,10,11,-1},
	{ 3, 4,11,12},
	{ 4, 5,12,13},
	{ 5,13,14,-1},
	{ 6,-1,-1,-1},
	{ 6, 7,-1,-1},
	{ 7, 8,-1,-1},
	{ 8, 9,-1,-1},
	{ 9,-1,-1,-1}
};

int dist[15][15]; // dist[i][j] := ( テ」ツδ榲」ツつケ i テ」ツ?ォテ」ツ?づ」ツつ凝ヲツ閉ーテ・ツュツ療」ツつ津」ツδ榲」ツつケ j テ」ツ?ォテァツァツサテ・ツ仰陛」ツ?凖」ツつ凝」ツ?淌」ツつ?」ツ?ョテヲツ慊?ァツ淞ュテヲツ可凝ヲツ閉ー )

int n,a[15];

int hstar(int now){
	int sum=0;
	rep(i,n) if(a[i]!=0) sum+=dist[a[i]][i];
	return now+sum;
}

int ub;
bool dfs(int now,int p,int pre,int end){
	if(end==n) return true;

	if(hstar(now)>ub) return false;

	// rep(k,4){
	for(int k=3;k>=0;k--){ // テゥツ??ゥツ??」ツ?ォティツェツソテ」ツ?ケテ」ツ?淌ヲツ鳴ケテ」ツ??10 テァツァツ津」ツ?湘」ツつ嘉」ツ??ゥツ?淌」ツ??( テ」ツδ?」ツつケテ」ツδ暗」ツつアテ」ツδシテ」ツつケテ」ツ?ョテァツ可ケテヲツ?ァ?? )
		int q=nei[p][k];
		if(q==-1 || q>=n || q==pre) continue; // テァツ崢エテ・ツ可催」ツ?ョテァツ環カテヲツ?凝」ツ?ォテ」ツ?ッテゥツ?キテァツァツサテ」ツ?療」ツ?ェテ」ツ??
		swap(a[p],a[q]);
		int end2=end-(a[q]==p?1:0)-(a[p]==q?1:0)+(a[p]==p?1:0)+(a[q]==q?1:0);
		if(dfs(now+1,q,p,end2)) return true;
		swap(a[p],a[q]);
	}
	return false;
}

int main(){
	rep(i0,15){
		rep(i,15) dist[i0][i]=77;
		dist[i0][i0]=0;
		int Q[32],head=0,tail=0; Q[tail++]=i0;
		while(head<tail){
			int i=Q[head++];
			rep(k,4){
				int j=nei[i][k];
				if(j!=-1 && dist[i0][j]==77) dist[i0][j]=dist[i0][i]+1, Q[tail++]=j;
			}
		}
	}

	for(int cas=1;scanf("%d",&n),n;cas++){
		n=n*(n+1)/2;
		rep(i,n) scanf("%d",a+i), a[i]--;

		int end=0; // テヲツ渉ε」ツ?」テ」ツ?ヲテ」ツ??」ツつ凝ヲツ閉ーテ・ツュツ療」ツ?ョテ・ツ?凝ヲツ閉ー
		rep(i,n) if(a[i]==i) end++;

		int p=find(a,a+15,0)-a;
		int h=(1<=p&&p<=2||6<=p&&p<=9?1:0); // 1 テ」ツ?ョテ」ツ?づ」ツつ凝ィツ。ツ?mod 2
		for(ub=h;ub<45;ub+=2) if(dfs(0,p,-1,end)) break;
		printf("Case %d: %d\n",cas,ub);
	}

	return 0;
}
accuracy: 1
time_ms: 5900
memory_kb: 1028
final_rank: 4

code_snippet: #include<iostream>
#include<queue>
#include<numeric>
#include<cstdio>
#include<queue>
#include<cassert>
#include<vector>
#include<set>
#include<map>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
const int inf = 100;
const int N = 5;
const int dy[]={1,1,-1,-1};
const int dx[]={0,1,0, -1};

const int wdy[2] = {-1,1};
int edge[66605][N][N];
int wdcost[N+1][66605];
class st{
public:
  int mat[N][N];
  st(){
    rep(i,N)rep(j,N)mat[i][j] = 0;
    rep(i,N)mat[i][i] = N-i;
    mat[0][0] = N-1;
  }
  bool operator<(const st & a)const{
    rep(i,N)rep(j,N)if (mat[i][j] != a.mat[i][j])return mat[i][j] < a.mat[i][j];
    return false;
  }
};

int getst(st &now,map<st,int> & M){
  int index = M.size();
  if (M.count(now) == 0)M[now] = index;
  return M[now];
}

map<st,int> NUM;
void makeall(){
  map<st,int> M;
  queue<st> Q;
  st ini;
  Q.push(ini);
  M.insert(make_pair(ini,0));
  while(!Q.empty()){
    st now = Q.front();Q.pop();
    int nownum = getst(now,NUM);
    int tc = M[now];
    wdcost[N][nownum] = tc;
    rep(i,N){
      if (accumulate(now.mat[i],now.mat[i+1],0) == N-i)continue;
      rep(j,N){
	rep(k,2){
	  int ney = i+wdy[k];
	  if (ney == -1 || ney == N)continue;
	  if (now.mat[ney][j] == 0)continue;
	  st next = now;
	  next.mat[i][j]++;
	  next.mat[ney][j]--;
	  int nextnum = getst(next,NUM);
	  edge[nownum][ney][j] = nextnum;
	  if (M.count(next) == 0){
	    M.insert(make_pair(next,tc+1));
	    Q.push(next);
	  }
	}
      }
    }
  }
}

int row[15];
int col[15];
void precalcWD(){
  const int ori[N][N]={
    1,3,6,10,15,
    2,5,9,14,0,
    4,8,13,0,0,
    7,12,0,0,0,
    11,0,0,0,0,
  };
  rep(i,N){
    rep(j,N){
      if (ori[i][j] == 1 || ori[i][j] == 0)continue;
      row[ori[i][j]] = i;
      col[ori[i][j]] = j;
    }
  }
}

pair<int,int> getWD(int n,int cpy[N][N]){
  if (n != 5)return make_pair(0,0);
  st r,c;
  int inp[N][N]={0};
  rep(j,N){
    int p = 0;
    rep(i,N){
      if (cpy[i][j] == 0)continue;
      inp[p++][j] = cpy[i][j];
    }
  }
  int matr[N][N]={},matc[N][N]={};
  rep(i,N){
    rep(j,N){
      if (inp[i][j] == 0 || inp[i][j] == 1)continue;
      matr[i][row[inp[i][j]]]++;
      matc[j][col[inp[i][j]]]++;
    }
  }


  //int wdr,wdc;
  rep(i,N)rep(j,N)r.mat[i][j] = matr[i][j];
  rep(i,N)rep(j,N)c.mat[i][j] = matc[i][j];
  return make_pair(NUM[r],NUM[c]);
}

void initWD(){
  rep(i,66605)rep(j,N)rep(k,N)edge[i][j][k] = -1;
  makeall();
  precalcWD();
}

//-------------------------------------------------------------------------------------
int mcost[N*N][N][N];
void precalc(int n){
  int pos[n][n];
  int p=0;
  rep(i,n){
    rep(j,i+1){
      rep(k,n)rep(l,k+1)mcost[p][k][l] = inf;
      mcost[p][i][j] = 0;
      pos[i][j] = p;
      p++;
    }
  }
  while(true){
    bool isupdate=false;
    rep(ii,n){
      rep(jj,ii+1){
	int now = pos[ii][jj];
	rep(i,n){
	rep(j,i+1){
	  rep(k,4){
	    int ney = i+dy[k],nex = j+dx[k];
	    if (ney == -1 || nex == -1 || ney == n || ney < nex)continue;
	    if (ney == i && nex == i+1)continue;
	    if (mcost[now][ney][nex] > mcost[now][i][j]+1){
	      isupdate = true;
	      mcost[now][ney][nex] = mcost[now][i][j]+1;
	    }
	    if (mcost[now][i][j] > mcost[now][ney][nex] + 1){
	      isupdate = true;
	      mcost[now][i][j] = mcost[now][ney][nex]+1;
	    }
	  }
	}
	}
      }
    }
    if (!isupdate)break;
  }
}
//-------------------------------------------------------------------------------------

int in[N][N];
int geth(int n){
  rep(i,n)rep(j,i+1)mcost[0][i][j] = 0;

  int ret = 0;
  rep(i,n){
    rep(j,i+1){
      ret += mcost[in[i][j]-1][i][j];
    }
  }
  return ret;
}

int ans;
bool solve(int n,int cnt,int lim,int py,int px,int prev,int h,int wdr,int wdc,int y,int x){
  if (h == 0){
    ans = min(ans,cnt);
    return true;
  }
  if (cnt + h > lim){
    return false;
  }
  if (n == 5 && cnt + wdcost[5][wdr] + wdcost[5][wdc] > lim){
    return false;
  }
  rep(k,4){
    int ney = y+dy[k],nex = x+dx[k];
    if (ney == -1 || nex == -1 || ney == n || ney < nex)continue;
    if (in[ney][nex] == prev)continue;

    int nexth = h + (mcost[in[ney][nex]-1][y][x]-mcost[in[ney][nex]-1][ney][nex]);
    int nextwdr=wdr,nextwdc=wdc;
    if (n == 5){
      if (k == 0 || k == 2){//wdr -> nextwdr
	assert(nex == x);
	int base = x;
	nextwdr = edge[wdr][ney-base][row[in[ney][nex]]];
      }else {//wdc -> nextwdc
	nextwdc = edge[wdc][nex][col[in[ney][nex]]];
      }
    }
    swap(in[y][x],in[ney][nex]);
    bool ret;
    ret = solve(n,cnt+1,lim,-1,-1,in[y][x],nexth,nextwdr,nextwdc,ney,nex);
    swap(in[y][x],in[ney][nex]);
    if (ret)return true;
  }
  return false;
}

int main(){
  initWD();
  int n;
  int tc = 1;
  while(cin>>n && n){
    ans = inf;
    rep(i,n){
      rep(j,i+1){
	cin>>in[i][j];
      }
    }
    precalc(n);
    int sy,sx;
    rep(i,n)rep(j,i+1)if (in[i][j] == 1)sy = i,sx=j;
    int mod = mcost[0][sy][sx];
    int h = geth(n);
    int beg = 0;
    
    pair<int,int> wd = getWD(n,in);
    int wdr=wd.first,wdc=wd.second;

    if (mod%2 != 0)beg++;
    for(int i=beg;;i+=2){
      ans = inf;
      bool ret = solve(n,0,i,-1,-1,-1,h,wdr,wdc,sy,sx);
      if (ret){break;}
    }
    cout <<"Case " << tc++ << ": " << ans << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 5230
memory_kb: 25000
final_rank: 6

code_snippet: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

const int HALF = 22;
const ll BASE = 1e+9 + 7;
int n;
int N;
int posX[15];
int posY[15];
int dist[15][15];
const int dx[4] = { -1, 0, 0, 1 };
const int dy[4] = { -1, -1, 1, 1 };

inline int Encode(int x, int y) {
  assert(x <= y);
  return y * (y + 1) / 2 + x;
}
inline void Decode(int code, int &x, int &y) {
  assert(0 <= code && code < 15);
  x = posX[code];
  y = posY[code];
}

struct State {
  char cost;
  char a;
  char cards[15];
  int Get(int x, int y) {
    return cards[Encode(x, y)];
  }
  void Set(int x, int y, int v) {
    cards[Encode(x, y)] = v;
  }
  void Swap(int x1, int y1, int x2, int y2) {
    swap(cards[Encode(x1, y1)], cards[Encode(x2, y2)]);
  }
  void Holl(int &rx, int &ry) {
    REP(i, N) {
      if (cards[i] == 1) {
        rx = posX[i];
        ry = posY[i];
        return;
      }
    }
    assert(false);
  }
  int HollX() {
    int x, y;
    Holl(x, y);
    return x;
  }
  int HollY() {
    int x, y;
    Holl(x, y);
    return y;
  }
  void CalcA() {
    int rev[16];
    REP(i, N) {
      rev[(int)cards[i] - 1] = i;
    }

    a = 0;
    FOR(i, 1, N) {
      a += dist[rev[i]][i];
    }
    FOR(i, 3, N) {
      if (cards[i] == i + 1) { continue; }
      int fx = posX[i];
      int fy = posY[i];
      REP(dir, 4) {
        int nx = fx + dx[dir];
        int ny = fy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        if (cards[Encode(nx, ny)] != Encode(nx, ny) + 1) { goto next; }
      }
      a += 6;
next:;
    }
    if (a != 0 && n == 5) {
      if (cards[0] == 1 && cards[1] == 2 && cards[2] == 3) {
        a += 6;
      }
      if ((cards[0] == 1 || cards[1] == 1 || cards[2] == 1) &&
          (cards[3] == 4 && cards[4] == 5 && cards[5] == 6) &&
          (cards[6] != 7 || cards[7] != 8 || cards[8] != 9 ||
           cards[9] != 10 || cards[11] != 12 || cards[12] != 13 || cards[13] != 14)) {
        a += 6;
      }
      if ((cards[0] == 1 || cards[1] == 1 || cards[2] == 1 ||
           cards[3] == 1 || cards[4] == 1 || cards[5] == 1) &&
          (cards[6] == 7 || cards[7] == 8 || cards[8] == 9) &&
          (cards[9] != 10 || cards[11] != 12 || cards[12] != 13 || cards[13] != 14)) {
        a += 6;
      }
    }
  }
  ull Hash() {
    ll ret = 0;
    REP(i, N) {
      ret = ret * BASE + cards[i];
    }
    return ret;
  }
  bool operator<(const State &rhs) const {
    return cost + a > rhs.cost + rhs.a;
  }
};

map<ull, char> half[6];
void CalcHalfSide(int m) {
  n = m;
  N = n * (n + 1) / 2;
  State ini;
  ini.cost = 0;
  REP(i, N) { ini.cards[i] = i + 1; }
  queue<State> que;
  que.push(ini);
  half[m][ini.Hash()] = 0;

  while (!que.empty()) {
    State s = que.front();
    que.pop();
    if (s.cost == HALF) { continue; }

    int hx, hy;
    s.Holl(hx, hy);
    REP(dir, 4) {
      int nx = hx + dx[dir];
      int ny = hy + dy[dir];
      if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
      State ns = s;
      ns.Swap(hx, hy, nx, ny);
      ns.cost++;
      ull h = ns.Hash();
      if (half[m].count(h) && half[m][h] <=  ns.cost) { continue; }
      half[m][h] = ns.cost;
      que.push(ns);
    }
  }
}

int main() {
  REP(y, 5) {
    REP(x, y + 1) {
      posX[Encode(x, y)] = x;
      posY[Encode(x, y)] = y;
    }
  }
  FOREQ(i, 1, 5) { CalcHalfSide(i); }
  int test_case = 0;
  while (scanf("%d", &n), n) {
    test_case++;
    N = n * (n + 1) / 2;

    // calc dist
    MEMSET(dist, 0x0f);
    REP(i, N) { dist[i][i] = 0; }
    REP(i, N) {
      int fx = posX[i];
      int fy = posY[i];
      REP(dir, 4) {
        int nx = fx + dx[dir];
        int ny = fy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        dist[i][Encode(nx, ny)] = 1;
      }
    }
    REP(k, N) REP(i, N) REP(j, N) {
      dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    }

    // Get Input
    State ini;
    ini.cost = 0;
    REP(y, n) {
      REP(x, y + 1) {
        int v;
        scanf("%d", &v);
        ini.Set(x, y, v);
      }
    }
    if (ini.Get(0, n - 1) != Encode(0, n - 1) + 1) {
      ini.Swap(0, n - 1, 0, n - 2);
      ini.cost++;
    }
    if (ini.Get(n - 1, n - 1) != Encode(n - 1, n - 1) + 1) {
      ini.Swap(n - 1, n - 1, n - 2, n - 2);
      ini.cost++;
    }
    if (half[n].count(ini.Hash())) {
      printf("Case %d: %d\n", test_case, ini.cost + half[n][ini.Hash()]);
      continue;
    }
    ini.CalcA();
    int x, y;
    ini.Holl(x, y);

    // A*
    map<ull, int> dists;
    priority_queue<State> que;
    que.push(ini);
    dists[ini.Hash()] = 0;
    int ans = 45;
    while (!que.empty()) {
      State s = que.top();
      que.pop();
      if (s.a == 0) {
        ans = s.cost;
        break;
      }
      if (half[n].count(s.Hash())) {
        ans = min(ans, s.cost + half[n][s.Hash()]);
        //cout << "OK:" << " " << ans << endl;
        continue;
      }
      int hx, hy;
      s.Holl(hx, hy);
      REP(dir, 4) {
        int nx = hx + dx[dir];
        int ny = hy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        State ns = s;
        ns.Swap(hx, hy, nx, ny);
        ns.cost++;
        ns.CalcA();
        if (ns.cost > ans - HALF) { continue; }
        if (ns.cost + ns.a > ans) { continue; }
        ull h = ns.Hash();
        if (dists.count(h) && dists[h] <= ns.cost) { continue; }
        dists[h] = ns.cost;
        que.push(ns);
      }
    }
    printf("Case %d: %d\n", test_case, ans);
  }
}
accuracy: 1
time_ms: 5540
memory_kb: 59000
final_rank: 8

code_snippet: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

const int HALF = 21;
const ll BASE = 1e+9 + 7;
int n;
int N;
int posX[15];
int posY[15];
int dist[15][15];
const int dx[4] = { -1, 0, 0, 1 };
const int dy[4] = { -1, -1, 1, 1 };

inline int Encode(int x, int y) {
  assert(x <= y);
  return y * (y + 1) / 2 + x;
}
inline void Decode(int code, int &x, int &y) {
  assert(0 <= code && code < 15);
  x = posX[code];
  y = posY[code];
}

struct State {
  char cost;
  char a;
  char cards[15];
  int Get(int x, int y) {
    return cards[Encode(x, y)];
  }
  void Set(int x, int y, int v) {
    cards[Encode(x, y)] = v;
  }
  void Swap(int x1, int y1, int x2, int y2) {
    swap(cards[Encode(x1, y1)], cards[Encode(x2, y2)]);
  }
  void Holl(int &rx, int &ry) {
    REP(i, N) {
      if (cards[i] == 1) {
        rx = posX[i];
        ry = posY[i];
        return;
      }
    }
    assert(false);
  }
  int HollX() {
    int x, y;
    Holl(x, y);
    return x;
  }
  int HollY() {
    int x, y;
    Holl(x, y);
    return y;
  }
  void CalcA() {
    int rev[16];
    REP(i, N) {
      rev[(int)cards[i] - 1] = i;
    }

    a = 0;
    FOR(i, 1, N) {
      a += dist[rev[i]][i];
    }
    FOR(i, 3, N) {
      if (cards[i] == i + 1) { continue; }
      int fx = posX[i];
      int fy = posY[i];
      REP(dir, 4) {
        int nx = fx + dx[dir];
        int ny = fy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        if (cards[Encode(nx, ny)] != Encode(nx, ny) + 1) { goto next; }
      }
      a += 6;
next:;
    }
    if (a != 0 && n == 5) {
      if (cards[0] == 1 && cards[1] == 2 && cards[2] == 3) {
        a += 6;
      }
      if ((cards[0] == 1 || cards[1] == 1 || cards[2] == 1) &&
          (cards[3] == 4 && cards[4] == 5 && cards[5] == 6) &&
          (cards[6] != 7 || cards[7] != 8 || cards[8] != 9 ||
           cards[9] != 10 || cards[11] != 12 || cards[12] != 13 || cards[13] != 14)) {
        a += 6;
      }
      if ((cards[0] == 1 || cards[1] == 1 || cards[2] == 1 ||
           cards[3] == 1 || cards[4] == 1 || cards[5] == 1) &&
          (cards[6] == 7 || cards[7] == 8 || cards[8] == 9) &&
          (cards[9] != 10 || cards[11] != 12 || cards[12] != 13 || cards[13] != 14)) {
        a += 6;
      }
    }
  }
  ull Hash() {
    ll ret = 0;
    REP(i, N) {
      ret = ret * BASE + cards[i];
    }
    return ret;
  }
  bool operator<(const State &rhs) const {
    return cost + a > rhs.cost + rhs.a;
  }
};

map<ull, char> half[6];
void CalcHalfSide(int m) {
  n = m;
  N = n * (n + 1) / 2;
  State ini;
  ini.cost = 0;
  REP(i, N) { ini.cards[i] = i + 1; }
  queue<State> que;
  que.push(ini);
  half[m][ini.Hash()] = 0;

  while (!que.empty()) {
    State s = que.front();
    que.pop();
    if (s.cost == HALF) { continue; }

    int hx, hy;
    s.Holl(hx, hy);
    REP(dir, 4) {
      int nx = hx + dx[dir];
      int ny = hy + dy[dir];
      if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
      State ns = s;
      ns.Swap(hx, hy, nx, ny);
      ns.cost++;
      ull h = ns.Hash();
      if (half[m].count(h) && half[m][h] <=  ns.cost) { continue; }
      half[m][h] = ns.cost;
      que.push(ns);
    }
  }
}

int main() {
  REP(y, 5) {
    REP(x, y + 1) {
      posX[Encode(x, y)] = x;
      posY[Encode(x, y)] = y;
    }
  }
  FOREQ(i, 1, 5) { CalcHalfSide(i); }
  int test_case = 0;
  while (scanf("%d", &n), n) {
    test_case++;
    N = n * (n + 1) / 2;

    // calc dist
    MEMSET(dist, 0x0f);
    REP(i, N) { dist[i][i] = 0; }
    REP(i, N) {
      int fx = posX[i];
      int fy = posY[i];
      REP(dir, 4) {
        int nx = fx + dx[dir];
        int ny = fy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        dist[i][Encode(nx, ny)] = 1;
      }
    }
    REP(k, N) REP(i, N) REP(j, N) {
      dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    }

    // Get Input
    State ini;
    ini.cost = 0;
    REP(y, n) {
      REP(x, y + 1) {
        int v;
        scanf("%d", &v);
        ini.Set(x, y, v);
      }
    }
    if (ini.Get(0, n - 1) != Encode(0, n - 1) + 1) {
      ini.Swap(0, n - 1, 0, n - 2);
      ini.cost++;
    }
    if (ini.Get(n - 1, n - 1) != Encode(n - 1, n - 1) + 1) {
      ini.Swap(n - 1, n - 1, n - 2, n - 2);
      ini.cost++;
    }
    ini.CalcA();
    int x, y;
    ini.Holl(x, y);

    // A*
    map<ull, int> dists;
    priority_queue<State> que;
    que.push(ini);
    dists[ini.Hash()] = 0;
    int ans = 45;
    while (!que.empty()) {
      State s = que.top();
      que.pop();
      if (s.a == 0) {
        ans = s.cost;
        break;
      }
      if (half[n].count(s.Hash())) {
        ans = min(ans, s.cost + half[n][s.Hash()]);
        //cout << "OK:" << " " << ans << endl;
        continue;
      }
      int hx, hy;
      s.Holl(hx, hy);
      REP(dir, 4) {
        int nx = hx + dx[dir];
        int ny = hy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        State ns = s;
        ns.Swap(hx, hy, nx, ny);
        ns.cost++;
        ns.CalcA();
        if (ns.cost > ans - HALF) { continue; }
        if (ns.cost + ns.a > ans) { continue; }
        ull h = ns.Hash();
        if (dists.count(h) && dists[h] <= ns.cost) { continue; }
        dists[h] = ns.cost;
        que.push(ns);
      }
    }
    printf("Case %d: %d\n", test_case, ans);
  }
}
accuracy: 1
time_ms: 5990
memory_kb: 50000
final_rank: 10

code_snippet: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

const int HALF = 22;
const ll BASE = 1e+9 + 7;
int n;
int N;
int posX[15];
int posY[15];
int dist[15][15];
const int dx[4] = { -1, 0, 0, 1 };
const int dy[4] = { -1, -1, 1, 1 };

inline int Encode(int x, int y) {
  assert(x <= y);
  return y * (y + 1) / 2 + x;
}
inline void Decode(int code, int &x, int &y) {
  assert(0 <= code && code < 15);
  x = posX[code];
  y = posY[code];
}

struct State {
  char cost;
  char a;
  char cards[15];
  int Get(int x, int y) {
    return cards[Encode(x, y)];
  }
  void Set(int x, int y, int v) {
    cards[Encode(x, y)] = v;
  }
  void Swap(int x1, int y1, int x2, int y2) {
    swap(cards[Encode(x1, y1)], cards[Encode(x2, y2)]);
  }
  void Holl(int &rx, int &ry) {
    REP(i, N) {
      if (cards[i] == 1) {
        rx = posX[i];
        ry = posY[i];
        return;
      }
    }
    assert(false);
  }
  int HollX() {
    int x, y;
    Holl(x, y);
    return x;
  }
  int HollY() {
    int x, y;
    Holl(x, y);
    return y;
  }
  void CalcA() {
    int rev[16];
    REP(i, N) {
      rev[(int)cards[i] - 1] = i;
    }

    a = 0;
    FOR(i, 1, N) {
      a += dist[rev[i]][i];
    }
    FOR(i, 3, N) {
      if (cards[i] == i + 1) { continue; }
      int fx = posX[i];
      int fy = posY[i];
      REP(dir, 4) {
        int nx = fx + dx[dir];
        int ny = fy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        if (cards[Encode(nx, ny)] != Encode(nx, ny) + 1) { goto next; }
      }
      a += 6;
next:;
    }
    if (a != 0 && n == 5) {
      if (cards[0] == 1 && cards[1] == 2 && cards[2] == 3) {
        a += 6;
      }
      if ((cards[0] == 1 || cards[1] == 1 || cards[2] == 1) &&
          (cards[3] == 4 && cards[4] == 5 && cards[5] == 6) &&
          (cards[6] != 7 || cards[7] != 8 || cards[8] != 9 ||
           cards[9] != 10 || cards[11] != 12 || cards[12] != 13 || cards[13] != 14)) {
        a += 6;
      }
      if ((cards[0] == 1 || cards[1] == 1 || cards[2] == 1 ||
           cards[3] == 1 || cards[4] == 1 || cards[5] == 1) &&
          (cards[6] == 7 || cards[7] == 8 || cards[8] == 9) &&
          (cards[9] != 10 || cards[11] != 12 || cards[12] != 13 || cards[13] != 14)) {
        a += 6;
      }
    }
  }
  ull Hash() {
    ll ret = 0;
    REP(i, N) {
      ret = ret * BASE + cards[i];
    }
    return ret;
  }
  bool operator<(const State &rhs) const {
    return cost + a > rhs.cost + rhs.a;
  }
};

map<ull, char> half[6];
void CalcHalfSide(int m) {
  n = m;
  N = n * (n + 1) / 2;
  State ini;
  ini.cost = 0;
  REP(i, N) { ini.cards[i] = i + 1; }
  queue<State> que;
  que.push(ini);
  half[m][ini.Hash()] = 0;

  while (!que.empty()) {
    State s = que.front();
    que.pop();
    if (s.cost == HALF) { continue; }

    int hx, hy;
    s.Holl(hx, hy);
    REP(dir, 4) {
      int nx = hx + dx[dir];
      int ny = hy + dy[dir];
      if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
      State ns = s;
      ns.Swap(hx, hy, nx, ny);
      ns.cost++;
      ull h = ns.Hash();
      if (half[m].count(h) && half[m][h] <=  ns.cost) { continue; }
      half[m][h] = ns.cost;
      que.push(ns);
    }
  }
}

int main() {
  REP(y, 5) {
    REP(x, y + 1) {
      posX[Encode(x, y)] = x;
      posY[Encode(x, y)] = y;
    }
  }
  FOREQ(i, 1, 5) { CalcHalfSide(i); }
  int test_case = 0;
  while (scanf("%d", &n), n) {
    test_case++;
    N = n * (n + 1) / 2;

    // calc dist
    MEMSET(dist, 0x0f);
    REP(i, N) { dist[i][i] = 0; }
    REP(i, N) {
      int fx = posX[i];
      int fy = posY[i];
      REP(dir, 4) {
        int nx = fx + dx[dir];
        int ny = fy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        dist[i][Encode(nx, ny)] = 1;
      }
    }
    REP(k, N) REP(i, N) REP(j, N) {
      dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    }

    // Get Input
    State ini;
    ini.cost = 0;
    REP(y, n) {
      REP(x, y + 1) {
        int v;
        scanf("%d", &v);
        ini.Set(x, y, v);
      }
    }
    if (ini.Get(0, n - 1) != Encode(0, n - 1) + 1) {
      ini.Swap(0, n - 1, 0, n - 2);
      ini.cost++;
    }
    if (ini.Get(n - 1, n - 1) != Encode(n - 1, n - 1) + 1) {
      ini.Swap(n - 1, n - 1, n - 2, n - 2);
      ini.cost++;
    }
    ini.CalcA();
    int x, y;
    ini.Holl(x, y);

    // A*
    map<ull, int> dists;
    priority_queue<State> que;
    que.push(ini);
    dists[ini.Hash()] = 0;
    int ans = 45;
    while (!que.empty()) {
      State s = que.top();
      que.pop();
      if (s.a == 0) {
        ans = s.cost;
        break;
      }
      if (half[n].count(s.Hash())) {
        ans = min(ans, s.cost + half[n][s.Hash()]);
        //cout << "OK:" << " " << ans << endl;
        continue;
      }
      int hx, hy;
      s.Holl(hx, hy);
      REP(dir, 4) {
        int nx = hx + dx[dir];
        int ny = hy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        State ns = s;
        ns.Swap(hx, hy, nx, ny);
        ns.cost++;
        ns.CalcA();
        if (ns.cost > ans - HALF) { continue; }
        if (ns.cost + ns.a > ans) { continue; }
        ull h = ns.Hash();
        if (dists.count(h) && dists[h] <= ns.cost) { continue; }
        dists[h] = ns.cost;
        que.push(ns);
      }
    }
    printf("Case %d: %d\n", test_case, ans);
  }
}
accuracy: 1
time_ms: 5610
memory_kb: 59000
final_rank: 9

code_snippet: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

const int HALF = 22;
const ll BASE = 1e+9 + 7;
int n;
int N;
int posX[15];
int posY[15];
int dist[15][15];
const int dx[4] = { -1, 0, 0, 1 };
const int dy[4] = { -1, -1, 1, 1 };

inline int Encode(int x, int y) {
  assert(x <= y);
  return y * (y + 1) / 2 + x;
}
inline void Decode(int code, int &x, int &y) {
  assert(0 <= code && code < 15);
  x = posX[code];
  y = posY[code];
}

struct State {
  char cost;
  char a;
  char cards[15];
  int Get(int x, int y) {
    return cards[Encode(x, y)];
  }
  void Set(int x, int y, int v) {
    cards[Encode(x, y)] = v;
  }
  void Swap(int x1, int y1, int x2, int y2) {
    swap(cards[Encode(x1, y1)], cards[Encode(x2, y2)]);
  }
  void Holl(int &rx, int &ry) {
    REP(i, N) {
      if (cards[i] == 1) {
        rx = posX[i];
        ry = posY[i];
        return;
      }
    }
    assert(false);
  }
  int HollX() {
    int x, y;
    Holl(x, y);
    return x;
  }
  int HollY() {
    int x, y;
    Holl(x, y);
    return y;
  }
  void CalcA() {
    int rev[16];
    REP(i, N) {
      rev[(int)cards[i] - 1] = i;
    }

    a = 0;
    FOR(i, 1, N) {
      a += dist[rev[i]][i];
    }
    FOR(i, 3, N) {
      if (cards[i] == i + 1) { continue; }
      int fx = posX[i];
      int fy = posY[i];
      REP(dir, 4) {
        int nx = fx + dx[dir];
        int ny = fy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        if (cards[Encode(nx, ny)] != Encode(nx, ny) + 1) { goto next; }
      }
      a += 6;
next:;
    }
    if (a != 0 && n == 5) {
      if (cards[0] == 1 && cards[1] == 2 && cards[2] == 3) {
        a += 6;
      }
      if ((cards[0] == 1 || cards[1] == 1 || cards[2] == 1) &&
          (cards[3] == 4 && cards[4] == 5 && cards[5] == 6) &&
          (cards[6] != 7 || cards[7] != 8 || cards[8] != 9 ||
           cards[9] != 10 || cards[11] != 12 || cards[12] != 13 || cards[13] != 14)) {
        a += 6;
      }
      if ((cards[0] == 1 || cards[1] == 1 || cards[2] == 1 ||
           cards[3] == 1 || cards[4] == 1 || cards[5] == 1) &&
          (cards[6] == 7 || cards[7] == 8 || cards[8] == 9) &&
          (cards[9] != 10 || cards[11] != 12 || cards[12] != 13 || cards[13] != 14)) {
        a += 6;
      }
    }
  }
  ull Hash() {
    ll ret = 0;
    REP(i, N) {
      ret = ret * BASE + cards[i];
    }
    return ret;
  }
  bool operator<(const State &rhs) const {
    return cost + a > rhs.cost + rhs.a;
  }
};

map<ull, char> half[6];
void CalcHalfSide(int m) {
  n = m;
  N = n * (n + 1) / 2;
  State ini;
  ini.cost = 0;
  REP(i, N) { ini.cards[i] = i + 1; }
  queue<State> que;
  que.push(ini);
  half[m][ini.Hash()] = 0;

  while (!que.empty()) {
    State s = que.front();
    que.pop();
    if (s.cost == HALF) { continue; }

    int hx, hy;
    s.Holl(hx, hy);
    REP(dir, 4) {
      int nx = hx + dx[dir];
      int ny = hy + dy[dir];
      if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
      State ns = s;
      ns.Swap(hx, hy, nx, ny);
      ns.cost++;
      ull h = ns.Hash();
      if (half[m].count(h) && half[m][h] <=  ns.cost) { continue; }
      half[m][h] = ns.cost;
      que.push(ns);
    }
  }
}

int main() {
  REP(y, 5) {
    REP(x, y + 1) {
      posX[Encode(x, y)] = x;
      posY[Encode(x, y)] = y;
    }
  }
  FOREQ(i, 1, 5) { CalcHalfSide(i); }
  int test_case = 0;
  while (scanf("%d", &n), n) {
    test_case++;
    N = n * (n + 1) / 2;

    // calc dist
    MEMSET(dist, 0x0f);
    REP(i, N) { dist[i][i] = 0; }
    REP(i, N) {
      int fx = posX[i];
      int fy = posY[i];
      REP(dir, 4) {
        int nx = fx + dx[dir];
        int ny = fy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        dist[i][Encode(nx, ny)] = 1;
      }
    }
    REP(k, N) REP(i, N) REP(j, N) {
      dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    }

    // Get Input
    State ini;
    ini.cost = 0;
    REP(y, n) {
      REP(x, y + 1) {
        int v;
        scanf("%d", &v);
        ini.Set(x, y, v);
      }
    }
    if (ini.Get(0, n - 1) != Encode(0, n - 1) + 1) {
      ini.Swap(0, n - 1, 0, n - 2);
      ini.cost++;
    }
    if (ini.Get(n - 1, n - 1) != Encode(n - 1, n - 1) + 1) {
      ini.Swap(n - 1, n - 1, n - 2, n - 2);
      ini.cost++;
    }
    ini.CalcA();
    int x, y;
    ini.Holl(x, y);

    // A*
    map<ull, int> dists;
    priority_queue<State> que;
    que.push(ini);
    dists[ini.Hash()] = 0;
    int ans = 45;
    while (!que.empty()) {
      State s = que.top();
      que.pop();
      if (s.a == 0) {
        ans = s.cost;
        break;
      }
      if (half[n].count(s.Hash())) {
        ans = min(ans, s.cost + half[n][s.Hash()]);
        //cout << "OK:" << " " << ans << endl;
      }
      int hx, hy;
      s.Holl(hx, hy);
      REP(dir, 4) {
        int nx = hx + dx[dir];
        int ny = hy + dy[dir];
        if (nx < 0 || nx > ny || ny < 0 || ny >= n) { continue; }
        State ns = s;
        ns.Swap(hx, hy, nx, ny);
        ns.cost++;
        ns.CalcA();
        if (ns.cost > ans - HALF) { continue; }
        if (ns.cost + ns.a > ans) { continue; }
        ull h = ns.Hash();
        if (dists.count(h) && dists[h] <= ns.cost) { continue; }
        dists[h] = ns.cost;
        que.push(ns);
      }
    }
    printf("Case %d: %d\n", test_case, ans);
  }
}
accuracy: 1
time_ms: 5510
memory_kb: 0
final_rank: 3

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
using namespace std;

#define rep(i,n) for(int i = 0; i < (int)n; i++)
#define dbg(x) cerr << #x << " = " << (x) << endl;
typedef long long ll;
typedef vector<int> vi;

void solve_small(vi);

const int dy[] = {-1, -1, 1, 1}, dx[] = {-1, 0, 0, 1};
map<ll, int> M;
int n, num[5][5];

inline ll hash(const vi &v){
	ll res = 0;
	rep(i,v.size()) res *= 17, res += v[i];
	return res;
}
inline void push(const vi &v, int c, queue<pair<int,vi> > &q){
	ll h = hash(v);
	if(M.count(h))return;
	M[h] = c;
	if(c <= 22) q.push(make_pair(c+1, v));
}

int main(){
	
	queue<pair<int,vi> > q;
	vi goal;
	int k = 0;
	rep(i,5) rep(j,i+1){
		num[i][j] = k;
		goal.push_back(++k);
	}
	push(goal, 0, q);
	
	while(!q.empty()){
		vi v = q.front().second;
		int c = q.front().first; q.pop();
		
		int idx = -1, y, x;
		for(y = 0; y < 5; y++) for(x = 0; x <= y; x++)
			if(v[++idx] == 1) goto OUT;
		OUT:;
		rep(d,4){
			int ny = y + dy[d], nx = x + dx[d];
			if(ny < 0 || nx < 0 || ny >= 5 || nx > ny) continue;
			swap(v[num[ny][nx]], v[idx]);
			push(v, c, q);
			swap(v[num[ny][nx]], v[idx]);
		}
	}
	int cs = 0;
	
	while(cin >> n, n){
		
		cout << "Case " << ++cs << ": ";
		
		vi v(n*(n+1)/2);
		k = 0;
		rep(i,n) rep(j,i+1) cin >> v[k++];
		if(n <= 4){
			solve_small(v);
			continue;
		}
		
		ll h = hash(v);
		if(M.count(h)){
			cout << M[h] << endl;
			continue;
		}
		
		queue<pair<int,vi> > q;
		set<ll> s;
		s.insert(h);
		q.push(make_pair(0, v));
		while(!q.empty()){
			v = q.front().second;
			int c = q.front().first; q.pop();
			
			int idx = -1, y, x;
			for(y = 0; y < 5; y++) for(x = 0; x <= y; x++)
				if(v[++idx] == 1) goto OUT2;
			OUT2:;
			rep(d,4){
				int ny = y + dy[d], nx = x + dx[d];
				if(ny < 0 || nx < 0 || ny >= 5 || nx > ny) continue;
				swap(v[num[ny][nx]], v[idx]);
				ll h = hash(v);
				if(M.count(h)){
					cout << M[h] + c + 1 << endl;
					goto END;
				}
				if(!s.count(h)) q.push(make_pair(c+1, v)), s.insert(h);
				swap(v[num[ny][nx]], v[idx]);
			}
		}
		END:;
	}
	return 0;
}

void solve_small(vi v){
	vi goal = v;
	sort(goal.begin(), goal.end());
	queue<pair<int,vi> > q;
	set<ll> s;
	ll ghash = hash(goal);
	q.push(make_pair(0, v));
	
	while(!q.empty()){
		v = q.front().second;
		int c = q.front().first; q.pop();
		ll h = hash(v);
		if(s.count(h)) continue;
		s.insert(h);
		if(h == ghash){
			cout << c <<endl; return;
		}
		int idx = -1, y, x;
		for(y = 0; y < 5; y++) for(x = 0; x <= y; x++)
			if(v[++idx] == 1) goto OUT3;
		OUT3:;
		rep(d,4){
			int ny = y + dy[d], nx = x + dx[d];
			if(ny < 0 || nx < 0 || ny >= n || nx > ny) continue;
			swap(v[num[ny][nx]], v[idx]);
			if(!s.count(hash(v))) q.push(make_pair(c+1, v));
			swap(v[num[ny][nx]], v[idx]);
		}
	}
}
accuracy: 1
time_ms: 5310
memory_kb: 0
final_rank: 2

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
using namespace std;

#define rep(i,n) for(int i = 0; i < (int)n; i++)
#define dbg(x) cerr << #x << " = " << (x) << endl;
typedef long long ll;
typedef vector<int> vi;

void solve_small(vi);

const int dy[] = {-1, -1, 1, 1}, dx[] = {-1, 0, 0, 1};
map<ll, int> M;
int n, num[5][5];

inline ll hash(const vi &v){
	ll res = 0;
	rep(i,v.size()) res *= 17, res += v[i];
	return res;
}
inline void push(const vi &v, int c, queue<pair<int,vi> > &q){
	ll h = hash(v);
	if(M.count(h) || c > 22) return;
	M[h] = c;
	q.push(make_pair(c+1, v));
}

void pv(const vi &v){
	int k = 0;
	rep(i,n) rep(j,i+1) cerr << v[k++] << (j==i?"\n":" ");
}

int main(){
	
	queue<pair<int,vi> > q;
	vi goal;
	int k = 0;
	rep(i,5) rep(j,i+1){
		num[i][j] = k;
		goal.push_back(++k);
	}
	push(goal, 0, q);
	
	while(!q.empty()){
		vi v = q.front().second;
		int c = q.front().first; q.pop();
		/*
		dbg(c);
		if(c == 2) pv(v);
		*/
		int idx = -1, y, x;
		for(y = 0; y < 5; y++) for(x = 0; x <= y; x++)
			if(v[++idx] == 1) goto OUT;
		OUT:;
		rep(d,4){
			int ny = y + dy[d], nx = x + dx[d];
			if(ny < 0 || nx < 0 || ny >= 5 || nx > ny) continue;
			swap(v[num[ny][nx]], v[idx]);
			push(v, c, q);
			swap(v[num[ny][nx]], v[idx]);
		}
	}
	
	int cs = 0;
	
	while(cin >> n, n){
		
		cout << "Case " << ++cs << ": ";
		
		vi v(n*(n+1)/2);
		k = 0;
		rep(i,n) rep(j,i+1) cin >> v[k++];
		if(n <= 4){
			solve_small(v);
			continue;
		}
		
		ll h = hash(v);
		if(M.count(h)){
			cout << M[h] << endl;
			continue;
		}
		
		queue<pair<int,vi> > q;
		set<ll> s;
		s.insert(h);
		q.push(make_pair(0, v));
		while(!q.empty()){
			v = q.front().second;
			int c = q.front().first; q.pop();
			
			int idx = -1, y, x;
			for(y = 0; y < 5; y++) for(x = 0; x <= y; x++)
				if(v[++idx] == 1) goto OUT2;
			OUT2:;
			rep(d,4){
				int ny = y + dy[d], nx = x + dx[d];
				if(ny < 0 || nx < 0 || ny >= 5 || nx > ny) continue;
				swap(v[num[ny][nx]], v[idx]);
				ll h = hash(v);
				if(M.count(h)){
					cout << M[h] + c + 1 << endl;
					goto END;
				}
				if(!s.count(h)) q.push(make_pair(c+1, v)), s.insert(h);
				swap(v[num[ny][nx]], v[idx]);
			}
		}
		END:;
	}
	return 0;
}

void solve_small(vi v){
	vi goal = v;
	sort(goal.begin(), goal.end());
	queue<pair<int,vi> > q;
	set<ll> s;
	ll ghash = hash(goal);
	q.push(make_pair(0, v));
	
	//rep(i,v.size())cerr<<v[i]<<(i==v.size()-1?"\n":" ");
	
	while(!q.empty()){
		v = q.front().second;
		int c = q.front().first; q.pop();
		ll h = hash(v);
		if(s.count(h)) continue;
		s.insert(h);
		if(h == ghash){
			cout << c <<endl; return;
		}
		/*
		cerr<<endl;
		int k = 0;
		rep(i,n) rep(j,i+1) cerr << v[k++] << (j==i?"\n":" ");
		*/
		int idx = -1, y, x;
		for(y = 0; y < 5; y++) for(x = 0; x <= y; x++)
			if(v[++idx] == 1) goto OUT3;
		OUT3:;
		rep(d,4){
			int ny = y + dy[d], nx = x + dx[d];
			if(ny < 0 || nx < 0 || ny >= n || nx > ny) continue;
			swap(v[num[ny][nx]], v[idx]);
			if(!s.count(hash(v))) q.push(make_pair(c+1, v));
			swap(v[num[ny][nx]], v[idx]);
		}
	}
}
accuracy: 1
time_ms: 6510
memory_kb: 0
final_rank: 7