public double h
        (
            MAM_AgentState state,
            MAM_AgentState parent
        )
        {
            int dim = 2;

            int[] curr = { state.lastMove.x, state.lastMove.y };

            if (parent == null)
            {
                state.h          = CalculateInitialH();
                state.hToMeeting = 0;
                for (int i = 0; i < dim; i++)
                {
                    state.hToMeeting += Math.Abs(curr[i] - medians[i][1]);
                }
                return(state.h);
            }

            MAM_AgentState[] startStates = instance.m_vAgents;
            state.h          = 0;
            state.hToMeeting = 0;
            int[] start = { startStates[instance.GetAgentIndexInArray(state.agentIndex)].lastMove.x, startStates[instance.GetAgentIndexInArray(state.agentIndex)].lastMove.y };

            for (int i = 0; i < dim; i++)
            {
                if (medians[i].Length == 2) // even number of agents
                {
                    if (medians[i][0] < start[i] && medians[i][0] < curr[i])
                    {
                        state.h          += h0[i] - start[i] + curr[i];
                        state.hToMeeting += curr[i] - medians[i][0];
                    }
                    else if (start[i] < medians[i][1] && curr[i] < medians[i][1])
                    {
                        state.h          += h0[i] + start[i] - curr[i];
                        state.hToMeeting += medians[i][1] - curr[i];
                    }
                    else if (start[i] <= medians[i][0] && medians[i][1] <= curr[i])
                    {
                        state.h          += h0[i] + start[i] + curr[i] - 2 * medians[i][1];
                        state.hToMeeting += curr[i] - medians[i][1];
                    }
                    else // i.e., curr[i] <= medians[i][0] && medians[i][1] <= start[i]
                    {
                        state.h          += h0[i] - start[i] - curr[i] + 2 * medians[i][0];
                        state.hToMeeting += medians[i][0] - curr[i];
                    }
                }
                else // odd number of agents
                {
                    if (medians[i][1] < start[i] && medians[i][1] < curr[i])
                    {
                        state.h          += h0[i] - start[i] + curr[i];
                        state.hToMeeting += curr[i] - medians[i][1];
                    }
                    else if (start[i] < medians[i][1] && curr[i] < medians[i][1])
                    {
                        state.h          += h0[i] + start[i] - curr[i];
                        state.hToMeeting += medians[i][1] - curr[i];
                    }
                    else if (start[i] <= medians[i][1] && medians[i][1] <= curr[i])
                    {
                        state.h          += h0[i] + start[i] - medians[i][1] + Math.Max(curr[i] - medians[i][2], 0);
                        state.hToMeeting += Math.Max(curr[i] - medians[i][2], 0);
                    }
                    else // i.e., curr[i] <= medians[i][1] && medians[i][1] <= start[i]
                    {
                        state.h          += h0[i] - start[i] + medians[i][1] + Math.Max(medians[i][0] - curr[i], 0);
                        state.hToMeeting += Math.Max(medians[i][0] - curr[i], 0);
                    }
                }
            }
            // for debug

            /*AgentState temp = startStates[state.agentIndex];
             * startStates[state.agentIndex] = state;
             * double debug = CalculateH(startStates);
             * if (debug != state.h)
             *  Console.WriteLine("ERROR!!!");
             * startStates[state.agentIndex] = temp;*/
            return(state.h);
        }