public AvgPathMove(int[,] p, string move, AvgPathMove parent)
        {
            if (parent == null) level = 0;
            else level = parent.level + 1;

            this.parent = parent;
            this.p = p;
            this.move = move;
            pos = GenPos();

            score = GetScore(p);
        }
        public static string[] Solve(int[,] initial, ref int countStep, int maxStep, long durationPerClickMs, long timeLimitMs)
        { 

#if TRIAL
            maxStep = 25;
#endif

            InitializeDatabase();


            int[] count = new int[maxStep + 1];
            AvgPathMove bestAnswer = null;

            BinaryHeap[] nextQueue = new BinaryHeap[6];
            for (int color = 1; color < 6; color++)
                nextQueue[color] = new BinaryHeap();

            Hashtable used = new Hashtable();

            for (int color = 1; color < 6; color++)
            {
                int[,] initialColor = new int[9, 9];
                for (int i = 0; i < 9; i++)
                    for (int j = 0; j < 9; j++)
                        initialColor[i, j] = (initial[i, j] == color) ? 1 : 0;

                AvgPathMove firstMove = new AvgPathMove(initialColor, null, null);
                nextQueue[color].Insert(firstMove.score, firstMove);
                used[firstMove.pos] = true;

                if (FoundSolution(firstMove, maxStep))
                {
                    bestAnswer = firstMove;
                    break;
                }
            }


            long startTime = System.DateTime.Now.Ticks;
            while (bestAnswer == null)
            {
                if (((System.DateTime.Now.Ticks - startTime) / TimeSpan.TicksPerMillisecond) > timeLimitMs)
                    return null;

                bool isBreak = true;
                for (int color = 1; color < 6; color++)
                    if (nextQueue[color].Count > 0) isBreak = false;

                if (isBreak == true) break;

                countStep++;

                bool end = false;
                for (int color = 1; color < 6; color++)
                {
                    AvgPathMove m = (AvgPathMove)(nextQueue[color].Remove());

                    AvgPathMove[] newMoves = new AvgPathMove[] {
                        m.next(0,'U'),m.next(1,'U'), m.next(2,'U'),
                        m.next(0,'D'),m.next(1,'D'), m.next(2,'D'),
                        m.next(0,'R'),m.next(1,'R'), m.next(2,'R'),
                        m.next(0,'L'),m.next(1,'L'), m.next(2,'L')
                    };


                    for (int i = 0; i < newMoves.Length; i++)
                    {
                        if (used[newMoves[i].pos] != null) continue;

                        if (FoundSolution(newMoves[i], maxStep))
                        {
                            bestAnswer = newMoves[i];
                            end = true;
                            break;
                        }

#if TRIAL
                        if (newMoves[i].level >= 19) continue;
#else
                        if (newMoves[i].level >= (maxStep - 6)) continue;
#endif

                        count[newMoves[i].level]++;


                        used[newMoves[i].pos] = true;

 
                        nextQueue[color].Insert(newMoves[i].score, newMoves[i]);

                    }

                    if (end == true) break;
                }

                if (end == true) break;
            }

            if (bestAnswer == null) return null;

            //refAnswer = bestAnswer;
            string[] steps = new string[bestAnswer.level];

            AvgPathMove b = bestAnswer;
            for (int i = steps.Length - 1; i >= 0; i--)
            {
                steps[i] = b.move;
                b = b.parent;
            }

            string[] contSteps = GetSolution(bestAnswer);

            string[] final = new string[steps.Length + contSteps.Length];
            for (int i = 0; i < steps.Length; i++)
                final[i] = steps[i];

            for (int i = 0; i < contSteps.Length; i++)
                final[i + steps.Length] = contSteps[i];

            conn.Close();

            return final;
        }
        private static bool FoundSolution(AvgPathMove bestPathMove, int maxStep)
        {

            DbCommand cmd = conn.CreateCommand();

#if TRIAL
            cmd.CommandText = "SELECT COUNT(1) FROM block_colors WHERE pos='" + bestPathMove.pos + "' AND num_steps = " + (25 - bestPathMove.level);
#else
            cmd.CommandText = "SELECT COUNT(1) FROM block_colors WHERE pos='" + bestPathMove.pos + "' AND num_steps <= " + (maxStep - bestPathMove.level);
#endif

            long num = (long)cmd.ExecuteScalar();
            cmd.Dispose();

            if (num > 0) return true;
            else return false;
        }
        private static string[] GetSolution(AvgPathMove bestPathMove)
        {
            List<string> buffer = new List<string>();

            while (true)
            {
                if (bestPathMove.IsFinish()) break;

                DbCommand cmd = conn.CreateCommand();
                cmd.CommandText = "SELECT move FROM block_colors WHERE pos='" + bestPathMove.pos + "'";

                string move = (string)cmd.ExecuteScalar();

                if (move == "") break;

                char[] c = move.ToCharArray();

                if (c[1] == 'U') c[1] = 'D';
                else if (c[1] == 'D') c[1] = 'U';
                else if (c[1] == 'L') c[1] = 'R';
                else if (c[1] == 'R') c[1] = 'L';

                string reverseMove = c[0] + "" + c[1];

                buffer.Add(reverseMove);
                cmd.Dispose();

                bestPathMove = bestPathMove.next(int.Parse(c[0] + ""), c[1]);
            }

            return buffer.ToArray();
        }