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 JAVA (judge verdict: Time Limit Exceeded)

import java.util.Scanner;

public class Main {
	
	public static final int INF = Integer.MAX_VALUE / 4 + 1;
	public static final int MAX = 15;
	
	public static int[][] lists = new int[3][MAX];
	public static int[]   sizes = new int[3];
	
	public static int[][] prevs = new int[3][MAX];
	public static int[] p_sizes = new int[3];
	
	public static void lists_clear(){
		sizes[0] = sizes[1] = sizes[2] = 0;
	}
	
	public static void prevs_clear(){
		p_sizes[0] = p_sizes[1] = p_sizes[2] = 0;
	}
	
	public static void all_clear(){
		lists_clear();
		prevs_clear();
	}
	
	public static void print_list(int l){
		System.out.print(l + "  :");
		for(int i = 0; i < sizes[l]; i++){
			System.out.print(" " + lists[l][i]);
		}
		System.out.println();
	}
	
	public static void print_prev_list(int l){
		System.out.print(l + " p:");
		for(int i = 0; i < p_sizes[l]; i++){
			System.out.print(" " + prevs[l][i]);
		}
		System.out.println();
	}
	
	public static boolean range_check(int i){
		return 0 <= i && i < 3;
	}
	
	public static boolean is_goal(int n){
		return sizes[0] == n && sizes[1] == 0 && sizes[2] == 0 || sizes[0] == 0 && sizes[1] == 0 && sizes[2] == n;
	}
	
	public static int get_list_top(int i){
		if(!range_check(i)){
			return 0;
		}else if(sizes[i] == 0){
			return 0;
		}else{
			return lists[i][sizes[i] - 1];
		}
	}
	
	public static void save_to_prev(){
		for(int i = 0; i < 3; i++){
			p_sizes[i] = sizes[i];
			
			for(int j = 0; j < sizes[i]; j++){
				prevs[i][j] = lists[i][j];
			}
		}
	}
	
	public static void restore_from_prev(){
		for(int i = 0; i < 3; i++){
			sizes[i] = p_sizes[i];
			
			for(int j = 0; j < p_sizes[i]; j++){
				lists[i][j] = prevs[i][j];
			}
		}
	}
	
	public static boolean is_same(){
		for(int i = 0; i < 3; i++){
			if(sizes[i] != p_sizes[i]){
				return false;
			}
			
			for(int j = 0; j < sizes[i]; j++){
				if(lists[i][j] != prevs[i][j]){
					return false;
				}
			}
		}
		
		return true;
	}
	
	public static void add_top(int l, int t){
		lists[l][sizes[l]] = t;
		sizes[l]++;
	}
	
	public static int remove_top(int l){
		int tmp = get_list_top(l);
		sizes[l]--;
		
		return tmp;
	}
	
	public static void do_move_nocheck(int cur, int pur){
		add_top(pur, remove_top(cur));
	}
	
	public static boolean can_move(int cur, boolean left){
		if(!range_check(cur)){
			return false;
		}else if(sizes[cur] == 0){
			return false;
		}
		
		final int pur = cur + (left ? -1 : 1);
		if(!range_check(pur)){
			return false;
		}
		
		final int cur_top = get_list_top(cur);
		final int pur_top = get_list_top(pur);
		
		if(cur_top <= pur_top){
			return false;
		}
		
		boolean same = false;
		
		do_move_nocheck(cur, pur);
		
		
		if(is_same()){
			same = true;
		}
		
		
		do_move_nocheck(pur, cur);
		
		if(same){
			return false;
		}else{
			return true;
		}
	}
	
	public static void do_forward_move(int cur, boolean left){
		final int pur = cur + (left ? -1 : 1);
		
		do_move_nocheck(cur, pur);
	}
	
	public static void do_backward_move(int cur, boolean left){
		final int pur = cur + (left ? -1 : 1);
		
		do_move_nocheck(pur, cur);
	}
	
	public static int dfs(final int n, int deep, final int m){
		if(deep > m){
			return INF;
		}
		
		if(is_goal(n)){
			/*
			System.out.println("--------------------");
			print_list(0);
			print_prev_list(0);
			print_list(1);
			print_prev_list(1);
			print_list(2);
			print_prev_list(2);
			*/
			return 0;
		}
		
		
		int min = INF;
		
		for(int left = 0; left < 2; left++){
			for(int cur = 0; cur < 3; cur++){
				boolean can = can_move(cur, left == 0);
				
				if(can){
					save_to_prev();
					
					do_forward_move(cur, left == 0);
					min = Math.min(min, dfs(n, deep + 1, m));
					do_backward_move(cur, left == 0);
					
					restore_from_prev();
				}
			}
		}
		
		return min + 1;
	}
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		while (true) {
			final int n = sc.nextInt();
			final int m = sc.nextInt();
			
			if(n == 0 && m == 0){
				break;
			}
			
			all_clear();
			
			for(int i = 0; i < 3; i++){
				sizes[i] = sc.nextInt();
				
				for(int j = 0; j < sizes[i]; j++){
					lists[i][j] = sc.nextInt();
				}
			}
			
			//boolean clear = false;
			int count = dfs(n, 0, m);
			
			/*
			for(count = 0; count <= m; count++){
				
				System.out.println(count + " : --------------------");
				print_list(0);
				print_prev_list(0);
				print_list(1);
				print_prev_list(1);
				print_list(2);
				print_prev_list(2);
				
				
				if(is_goal(n)){
					clear = true;
					break;
				}
				
				boolean min_left = false;
				int min_cur = 0;
				int min = Integer.MAX_VALUE;
				
				for(int left = 0; left < 2; left++){
					for(int cur = 0; cur < 3; cur++){
						int ret = move(cur, left == 0, false);
						
						if(ret != 0 && ret < min){
							min = ret;
							min_cur = cur;
							min_left = left == 0;
						}
					}
				}
				
				if(min != Integer.MAX_VALUE){
					move(min_cur, min_left, true);
				}else{
					System.out.println("ERROR");
				}
			}
			*/
			
			System.out.println(count <= m ? count : -1);
		}
	}

}