Problem:
大きさが異なる n 個のコップと 3 つのトレイ（お盆）A，B，C があり，それらのコップは 3 つのトレイの上にそれぞれ何個かずつ一山に重ねて置かれている．ただし，どのトレイにおいても，そのトレイの中で一番小さいコップが一番下に， 2 番目に小さいコップがその上に， 3 番目に小さいコップがその上にと，小さい順に伏せて重ねてある．例えば，下図の右側は， n = 5 個のコップがトレイ A，B，C にそれぞれ 2 個，0 個，3 個重ねて置かれている状態を示している．

このように，コップの初期状態が与えられたとき，次の規則 1 〜 3 を守りながら，すべてのコップを A または C のどちらかのトレイに移動させるには何回移動を行えばよいかを求めたい．

（規則 1） 1 回に 1 つのコップだけを移動させることができる．それは，そのトレイにあるコップの中で一番上のコップ（つまり，一番大きいコップ）である．

（規則 2）大きいコップの上に小さいコップを重ねてはいけない．

（規則 3）コップ 1 個の直接移動は，トレイ A から B，B から A，B から C，C から B のみが許され， A から C への直接移動や C から A への直接移動は許されない．

　n 個のコップの初期状態と整数 m が与えられたとき， m 回以内の移動で， A または C のどちらかのトレイにすべてのコップをまとめて重ねることができるかどうかを判定し，可能な場合には移動回数の最小値を，不可能な場合には -1 を出力するプログラムを作成しなさい．

　入力ファイルの 1 行目には， n と m がこの順に空白を区切り文字として書いてある． 1 ≦ n ≦ 15 であり， 1 ≦ m ≦ 15000000 である． 2 行目，3 行目，4 行目には， 1 から n までの整数を何個かずつ 3 つのグループに分けて，それぞれのグループ内で小さい順（昇順）に並べたものが書いてある．ただし，各行の先頭（それらの整数の前）には，それらの個数が書いてある． 2 行目に書かれている整数（先頭の 1 つを除く）はトレイ A の上に重ねられている各コップの大きさを表す．同様に， 3 行目に書かれている整数（先頭の 1 つを除く）はトレイ B の上に重ねられている各コップの大きさを表し， 4 行目に書かれている整数（先頭の１つを除く）はトレイ C の上に重ねられている各コップの大きさを表す．

入力例１

入力例２

入力例３

入力例４

3 10

4 20

2 5

3 3

0

2 1 2

2 1 2

0

1 1

1 3

0

1 1

2 2 3

1 4

0

2 2 3

　

出力例１

出力例２

出力例３

出力例４

9

3

0

-1

入力

入力は複数のデータセットからなる．n, m がともに 0 のとき入力が終了する．データセットの数は 5 を超えない．

出力

データセットごとに、移動回数または -1 を１行に出力する．

入力例

3 10
0
1 1
2 2 3
4 20
2 1 2
1 3
1 4
2 5
2 1 2
0
0
3 3
0
1 1
2 2 3
0 0

出力例

9
3
0
-1

各データセットの出力（移動回数または -1）の後に改行を入れること．

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;

// http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=2556344#3

public class CupState
{
	
	public byte[] A;
	public byte[] B;
	public byte[] C;
	public List<byte> Method;
	public byte LastM;
}


public class Test
{
	public static void Main()
	{
		while(true){
		  string[] str1 = Console.ReadLine().Split(' ');
		  int n = int.Parse(str1[0]); 
		  int m = int.Parse(str1[1]); 

		  if(n == 0) break;
		
		  int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), new Converter<string,int>(s => int.Parse(s)));
		  int[] b = Array.ConvertAll(Console.ReadLine().Split(' '), new Converter<string,int>(s => int.Parse(s)));
		  int[] c = Array.ConvertAll(Console.ReadLine().Split(' '), new Converter<string,int>(s => int.Parse(s)));
		  //Console.WriteLine("???????????? N = {0} P = {1} Ai = {2}", n, p, a);
		  Console.WriteLine(calc(n,m,a,b,c));
		
		
		}

	}

  public static int calc(int n,int m,int[] a,int[] b,int[] c) {
	  Stack<byte> aa = new Stack<byte>();
	  for(int i=1;i<a.Length;i++) aa.Push((byte)a[i]);
	  Stack<byte> bb = new Stack<byte>();
	  for(int i=1;i<b.Length;i++) bb.Push((byte)b[i]);
	  Stack<byte> cc = new Stack<byte>();
	  for(int i=1;i<c.Length;i++) cc.Push((byte)c[i]);
	  
	  byte[] aaa = new byte[a.Length-1];
	  for(int i=1;i<a.Length;i++) aaa[i-1] = (byte)a[i];
	  byte[] bbb = new byte[b.Length-1];
	  for(int i=1;i<b.Length;i++) bbb[i-1] = (byte)b[i];
	  byte[] ccc = new byte[c.Length-1];
	  for(int i=1;i<c.Length;i++) ccc[i-1] = (byte)c[i];
	  
	  //Console.WriteLine("A = {0} B = {1} C = {2}", String.Join("", aa), String.Join("", bb), String.Join("", cc));
/*
	  List<byte[][]> met = new List<byte[][]>();
	  met.Add(new byte[][]{aa.ToArray(),bb.ToArray(),cc.ToArray()});
	  
	  int t = calc_sub_dbg(0, m, aa, bb, cc, met);

	  foreach(byte[][] d in met) {
	    Console.WriteLine("==========");
	    foreach(byte[] e in d) Console.WriteLine(String.Join(" ", e));
	  }
	  Console.WriteLine("==========");
*/

	  int t = calc_sub_2(0, m, aaa, bbb, ccc);


	  return t;
  }
  
  
  public static int calc_sub_2(int cnt,int max,byte[] a,byte[] b,byte[] c) {
	
	List<CupState> mcsl = new List<CupState>();
	CupState cs = new CupState();
	cs.A = a; cs.B = b; cs.C = c; cs.Method = new List<byte>(); cs.LastM = 0;
	mcsl.Add(cs);
	List<CupState> ccsl = new List<CupState>();

	int mincnt = max;
	for(int i=0;i<=max;i++){
	  if(mcsl.Count == 0) break;
	  List<CupState> acsl = new List<CupState>();
      foreach(CupState ccs in mcsl){
		//Console.WriteLine(String.Join(" ", ccs.Method.ToArray()));
		
        if ((ccs.B.Length == 0) && ((ccs.A.Length == 0) || (ccs.C.Length == 0))){
          //if(ccs.Method.Count < mincnt) mincnt = ccs.Method.Count;
          if(i < mincnt) mincnt = i;
          ccsl.Add(ccs);
          continue;
        }
        //if (mincnt < ccs.Method.Count){
        //  continue;
        //}
        
        
        //int mode = (ccs.Method.Count==0) ? 0 : (int)ccs.Method[ccs.Method.Count-1];
        int va = (ccs.A.Length==0) ? -1 : (int)ccs.A[ccs.A.Length-1];
        int vb = (ccs.B.Length==0) ? -1 : (int)ccs.B[ccs.B.Length-1];
        int vc = (ccs.C.Length==0) ? -1 : (int)ccs.C[ccs.C.Length-1];
        
        //a->b
	    if((ccs.LastM != 2) && (vb < va)) {
	      CupState csa = new CupState();
          csa.A = new byte[ccs.A.Length-1];
          Array.Copy(ccs.A,0,csa.A,0,ccs.A.Length-1);
          csa.B = new byte[ccs.B.Length+1];
          Array.Copy(ccs.B,0,csa.B,0,ccs.B.Length);
          csa.B[csa.B.Length-1] = ccs.A[ccs.A.Length-1];
          csa.C = ccs.C;
          //csa.Method = new List<byte>(ccs.Method.ToArray());
          //csa.Method.Add(1);
          csa.LastM = 1;
          acsl.Add(csa);
	    }
        //b->a
	    if((ccs.LastM != 1) && (va < vb)) {
	      CupState csa = new CupState();
          csa.B = new byte[ccs.B.Length-1];
          Array.Copy(ccs.B,0,csa.B,0,ccs.B.Length-1);
          csa.A = new byte[ccs.A.Length+1];
          Array.Copy(ccs.A,0,csa.A,0,ccs.A.Length);
          csa.A[csa.A.Length-1] = ccs.B[ccs.B.Length-1];
          csa.C = ccs.C;
          //csa.Method = new List<byte>(ccs.Method.ToArray());
          //csa.Method.Add(2);
          csa.LastM = 2;
          acsl.Add(csa);
	    }
        //b->c
	    if((ccs.LastM != 4) && (vc < vb)) {
	      CupState csa = new CupState();
          csa.B = new byte[ccs.B.Length-1];
          Array.Copy(ccs.B,0,csa.B,0,ccs.B.Length-1);
          csa.C = new byte[ccs.C.Length+1];
          Array.Copy(ccs.C,0,csa.C,0,ccs.C.Length);
          csa.C[csa.C.Length-1] = ccs.B[ccs.B.Length-1];
          csa.A = ccs.A;
          //csa.Method = new List<byte>(ccs.Method.ToArray());
          //csa.Method.Add(3);
          csa.LastM = 3;
          acsl.Add(csa);
	    }
        //c->b
	    if((ccs.LastM != 3) && (vb < vc)) {
	      CupState csa = new CupState();
          csa.C = new byte[ccs.C.Length-1];
          Array.Copy(ccs.C,0,csa.C,0,ccs.C.Length-1);
          csa.B = new byte[ccs.B.Length+1];
          Array.Copy(ccs.B,0,csa.B,0,ccs.B.Length);
          csa.B[csa.B.Length-1] = ccs.C[ccs.C.Length-1];
          csa.A = ccs.A;
          //csa.Method = new List<byte>(ccs.Method.ToArray());
          //csa.Method.Add(4);
          csa.LastM = 4;
          acsl.Add(csa);
	    }
	  }
      mcsl = acsl;
      
	}
	
	return (ccsl.Count == 0) ? -1 : mincnt;
  }
  
  
  public static int calc_sub_1(int cnt,int max,Stack<byte>a,Stack<byte> b,Stack<byte> c, byte mode) {
	  if((a.Count==0) && (b.Count==0)) return cnt;
	  if((b.Count==0) && (c.Count==0)) return cnt;
	  if(max<cnt) return -1;
	  
	  int mincnt = max;
	  bool suc = false;
	  
	  //a->b
	  if((mode != 2) && (0<a.Count) && ((b.Count==0) || (b.Peek() < a.Peek()))) {
	    b.Push(a.Pop());
		int t = calc_sub_1(cnt+1, mincnt, a, b, c, 1);
		a.Push(b.Pop());
		if ((0<=t)&&(t<mincnt)) mincnt = t;
		if(0<=t) suc = true;
	  }
	  
	  //b->a
	  if((mode != 1) && (0<b.Count) && ((a.Count==0) || (a.Peek() < b.Peek()))) {
	    a.Push(b.Pop());
		int t = calc_sub_1(cnt+1, mincnt, a, b, c, 2);
		b.Push(a.Pop());
		if ((0<=t)&&(t<mincnt)) mincnt = t;
		if(0<=t) suc = true;
	  }
	  
	  //b->c
	  if((mode != 4) && (0<b.Count) && ((c.Count==0) || (c.Peek() < b.Peek()))) {
	    c.Push(b.Pop());
		int t = calc_sub_1(cnt+1, mincnt, a, b, c, 3);
		b.Push(c.Pop());
		if ((0<=t)&&(t<mincnt)) mincnt = t;
		if(0<=t) suc = true;
	  }
	  
	  //c->b
	  if((mode != 3) && (0<c.Count) && ((b.Count==0) || (b.Peek() < c.Peek()))) {
	    b.Push(c.Pop());
		int t = calc_sub_1(cnt+1, mincnt, a, b, c, 4);
		c.Push(b.Pop());
		if ((0<=t)&&(t<mincnt)) mincnt = t;
		if(0<=t) suc = true;
	  }
	  
	  if(suc) {
	    return mincnt;
	  } else {
		return -1;
	  }

  }
  
  public static int calc_sub_dbg(int cnt,int max,Stack<byte>a,Stack<byte> b,Stack<byte> c, List<byte[][]> met) {
	  if((a.Count==0) && (b.Count==0)) return cnt;
	  if((b.Count==0) && (c.Count==0)) return cnt;
	  if(max<cnt) return max+10;
	  
	  int mincnt = max+10;
	  List<byte[][]> m1 = new List<byte[][]>();
	  List<byte[][]> m2 = new List<byte[][]>();
	  List<byte[][]> m3 = new List<byte[][]>();
	  List<byte[][]> m4 = new List<byte[][]>();
	  int t1 = mincnt;
	  int t2 = mincnt;
	  int t3 = mincnt;
	  int t4 = mincnt;
	  
	  //a->b
	  if((0<a.Count) && ((b.Count==0) || (b.Peek() < a.Peek()))) {
	    Stack<byte> aa = CloneStack<byte>(a);
	    Stack<byte> bb = CloneStack<byte>(b);
	    bb.Push(aa.Pop());

		//m1.Add(new byte[][]{aa.ToArray(),bb.ToArray(),c.ToArray()});
		t1 = calc_sub_dbg(cnt+1, max, aa, bb, c, m1);
	  }
	  
	  //b->a
	  if((0<b.Count) && ((a.Count==0) || (a.Peek() < b.Peek()))) {
	    Stack<byte> aa = CloneStack<byte>(a);
	    Stack<byte> bb = CloneStack<byte>(b);
	    aa.Push(bb.Pop());

		//m2.Add(new byte[][]{aa.ToArray(),bb.ToArray(),c.ToArray()});
		t2 = calc_sub_dbg(cnt+1, max, aa, bb, c, m2);
	  }
	  
	  //b->c
	  if((0<b.Count) && ((c.Count==0) || (c.Peek() < b.Peek()))) {
	    Stack<byte> bb = CloneStack<byte>(b);
	    Stack<byte> cc = CloneStack<byte>(c);
	    cc.Push(bb.Pop());

		//m3.Add(new byte[][]{a.ToArray(),bb.ToArray(),cc.ToArray()});
		t3 = calc_sub_dbg(cnt+1, max, a, bb, cc, m3);
	  }
	  
	  //c->b
	  if((0<c.Count) && ((b.Count==0) || (b.Peek() < c.Peek()))) {
	    Stack<byte> bb = CloneStack<byte>(b);
	    Stack<byte> cc = CloneStack<byte>(c);
	    bb.Push(cc.Pop());

		//m4.Add(new byte[][]{a.ToArray(),bb.ToArray(),cc.ToArray()});
		t4 = calc_sub_dbg(cnt+1, max, a, bb, cc, m4);
	  }
	  
	  mincnt = Math.Min(Math.Min(t1,t2),Math.Min(t3,t4));
	  if(t1==mincnt) { met.AddRange(m1); return mincnt; }
	  if(t2==mincnt) { met.AddRange(m2); return mincnt; }
	  if(t3==mincnt) { met.AddRange(m3); return mincnt; }
	  if(t4==mincnt) { met.AddRange(m4); return mincnt; }
	  
	  return mincnt;
  }
  
    public static Stack<T> CloneStack<T>(Stack<T> original)
    {
        var arr = new T[original.Count];
        original.CopyTo(arr, 0);
        Array.Reverse(arr);
        return new Stack<T>(arr);
    }
  
  
  
  
  
  
}