private static string[] Calculate(int dx, int dy, int[] pieces, ref int countStep)
        {
            InitializeDatabase();

            BinaryHeap nextQueue = new BinaryHeap();
            Hashtable used = new Hashtable();

            Move finish = null;

            Move firstMove = new Move(pieces, "", null, dx, dy);
            nextQueue.Insert(firstMove.score, firstMove);

            int clickD = dx - 1;
            int clickD2 = clickD * clickD;

            used[firstMove.signature] = true;

            while (true)
            {
                if (nextQueue.Count == 0) break;

                countStep++;
                Move m = (Move)(nextQueue.Remove());
                if (m.IsFinished || FoundSolution(m,dx))
                {
                    finish = m;
                    break;
                }

                Move[] newMoves = new Move[clickD2*2];
                
                for (int k=0;k<newMoves.Length;k++)
                {
                    if ((k%2) == 0)
                        newMoves[k] = m.GenMove(k/2,Move.Direction.CLOCKWISE);
                    else
                        newMoves[k] = m.GenMove(k/2,Move.Direction.COUNTER_CLOCKWISE);
                }

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

                    if (newMoves[i].IsFinished || FoundSolution(m,dx))
                    {
                        finish = newMoves[i];
                        break;
                    }

                    if (used[newMoves[i].signature] != null) continue;

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

                    nextQueue.Insert(newMoves[i].score,newMoves[i]);
                    //Console.WriteLine(newMoves[i].ToString());
                    //Console.ReadKey();
                }

                if (finish != null) break;
            }

            if (finish == null) return null;

            if (!finish.IsFinished)
            {
                finish = GetSolution(finish,dx);
            }

            List<string> steps = new List<string>();

            while (finish != null)
            {
                steps.Insert(0, finish.move);
                finish = finish.parent;
            }

            steps.RemoveAt(0);

            return steps.ToArray();
        }
        private static Move Calculate44Border(int[] pieces, ref int countStep)
        {
            

            Move borderMove = null;
            BinaryHeap nextQueue = new BinaryHeap();
            Hashtable used = new Hashtable();

            Move firstMove = new Move(pieces, -1, null, 4, 4);
            nextQueue.Insert(firstMove.borderScore - firstMove.level / FACTOR, firstMove);

            used[firstMove.borderSignature] = true;

            while (true)
            {
                if (nextQueue.Count == 0) break;

                countStep++;
                //Console.WriteLine(countStep);

                Move m = (Move)(nextQueue.Remove());
                if (m.IsBorderFinished || FoundBorderSolution(m))
                {
                    borderMove = m;
                    break;
                }

                Move[] newMoves = new Move[] { m.DownMove(), m.UpMove(), m.RightMove(), m.LeftMove() };

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

                    
                    if (newMoves[i].IsBorderFinished || FoundBorderSolution(newMoves[i]))
                    {
                        borderMove = newMoves[i];
                        break;
                    }

                    if (used[newMoves[i].borderSignature] != null) continue;

                    //if (m.borderScore > (newMoves[i].borderScore+1)) continue;

                    used[newMoves[i].borderSignature] = true;
                    nextQueue.Insert(newMoves[i].borderScore - newMoves[i].level / FACTOR, newMoves[i]);
                    //Console.WriteLine(newMoves[i].ToBorderString());
                    //Console.WriteLine(newMoves[i].borderScore);

                    //if (newMoves[i].IsInvalid)
                        //Console.ReadKey();
                }

                if (borderMove != null) break;
            }

            if (!borderMove.IsBorderFinished)
            {
                borderMove = GetBorderSolution(borderMove);
            }

            //Console.WriteLine("4x4 border = " + countStep);
            conn.Clone();

            return borderMove;
        }
        public static string[] Solve(int[] food_limits, int[] spoon_limits,ref int countStep)
        {
            BinaryHeap nextQueue = new BinaryHeap();
            Hashtable used = new Hashtable();

            Move finish = null;

            int[] foods = new int[food_limits.Length];
            for (int i = 0; i < foods.Length; i++) foods[i] = 0;

            int[] spoons = new int[spoon_limits.Length];
            for (int i = 0; i < spoons.Length; i++) spoons[i] = 0;

            Move firstMove = new Move(foods,spoons,food_limits,spoon_limits,"",null);
            nextQueue.Insert(firstMove.score, firstMove);

            used[firstMove.signature] = true;

            while (true)
            {
                if (nextQueue.Count == 0) break;

                countStep++;
                Move m = (Move)(nextQueue.Remove());
                if (m.IsFinished)
                {
                    finish = m;
                    break;
                }

                Move[] newMoves = m.GenNextMoves();

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

                    if (newMoves[i].IsFinished)
                    {
                        finish = newMoves[i];
                        break;
                    }

                    if (used[newMoves[i].signature] != null) continue;

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

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

                if (finish != null) break;
            }

            if (finish == null) return null;

            List<string> steps = new List<string>();

            while (finish != null)
            {
                //Console.WriteLine(finish.ToString());
                steps.Insert(0, finish.move);
                finish = finish.parent;

                
            }

            steps.RemoveAt(0);

            return steps.ToArray();
        }