public ChiPhi TimSoLuongThietBi(double chiPhiDauTu, double Pr, double Ps, double Pf)
        {
            // reset lai cay search
            this.resetTree();
            List <SearchPosition> set = this.search;
            int    soMC         = 0;
            int    soDTD        = 0;
            int    soDB         = 0;
            double F_tong       = Double.MaxValue;
            int    MaxMC        = (int)(chiPhiDauTu / Pr);
            double F_best       = double.MaxValue;
            double F_underbound = 0.0;
            double F_last       = 0.0;
            int    best_pos     = 0;

            // set F_best = tong chi phi hien tai.
            foreach (SearchPosition s in set)
            {
                F_best += s.sumF2();
            }
            // Tieu hao luu tat cac cac F(N1, N2, N3)
            TieuHao F = new TieuHao();
            // vtMC, vtDTD, vtDB luu vi tri tam thoi cua cac thiet bi
            List <int[]> vtMC  = new List <int[]>();
            List <int[]> vtDTD = new List <int[]>();
            List <int[]> vtDB  = new List <int[]>();

            // Tim F(N1, 0, 0); 1 <= N1 <= N1_max
            for (int nMC = 1; nMC <= MaxMC; nMC++)
            {
                List <double> temp             = new List <double>();
                List <int>    viTriDatTrongCay = new List <int>();
                List <int>    viTriCay         = new List <int>();
                for (int j = 0; j < set.Count; j++)
                {
                    SearchPosition a    = set[j];
                    double         tong = 0;
                    for (int k = 0; k < set.Count; k++)
                    {
                        if (k != j)
                        {
                            tong += set[k].sumF1();
                        }
                    }
                    for (int i = 0; i < a.numNode; i++)
                    {
                        if (!a.getMC(i))
                        {
                            if (a.l[i] != 0 || a.d[i] != 0 || a.w[i] != 0)
                            {
                                a.setMC(i);
                                temp.Add(a.sumF1() + tong);
                                viTriCay.Add(j);
                                viTriDatTrongCay.Add(i);
                                a.refresh();
                            }
                        }
                    }
                }
                int vitri = findMinPos(temp);
                if (vitri == -1)
                {
                    break;
                }
                if (temp[vitri] > F_tong)
                {
                    break;
                }
                else
                {
                    F_tong = temp[vitri];
                }
                // set lai vi tri DTD trong cay
                set[viTriCay[vitri]].setLastMC(viTriDatTrongCay[vitri]);
                set[viTriCay[vitri]].refresh();
                // Cap nhat F_best;
                if (F_tong < F_best)
                {
                    F_best   = F_tong;
                    best_pos = F.currentLength();
                }
                Console.WriteLine(F_best.ToString() + "," + F_tong.ToString() + "," + F_underbound.ToString() + "," + nMC.ToString() + ",0, 0");
                // Them F(N1, 0, 0) vao N1 =1...N1_max;
                F.Add(nMC, 0, 0, F_tong, Clone(vtMC, new int[] { viTriCay[vitri], viTriDatTrongCay[vitri] }), vtDTD, vtDB);
                vtMC.Add(new int[] { viTriCay[vitri], viTriDatTrongCay[vitri] }); // Them vao vtMC
            }
            for (int nMC = 1; nMC <= MaxMC; nMC++)
            {
                // voi moi N1, N2 = 1...N2_max, N2_max = (chiPhiDauTu - so MC * Pr)/Ps;
                int MaxDTD = (int)((chiPhiDauTu - nMC * Pr) / Ps);
                vtMC = F.getMC_position(nMC, 0, 0); // Lay vi tri cac may cat cua truong hop F(nMC, 0, 0)
                // Neu khong tim duoc vtMC , ket thuc vong lap
                if (vtMC.Count == 0)
                {
                    break;
                }
                F_tong = F.getF(nMC, 0, 0);
                for (int nDTD = 1; nDTD <= MaxDTD; nDTD++)
                {
                    List <double> temp             = new List <double>();
                    List <int>    viTriDatTrongCay = new List <int>();
                    List <int>    viTriCay         = new List <int>();
                    for (int j = 0; j < set.Count; j++)
                    {
                        SearchPosition a    = set[j];
                        double         tong = 0;
                        for (int k = 0; k < set.Count; k++)
                        {
                            if (k != j)
                            {
                                tong += set[k].sumF1();
                            }
                        }
                        for (int i = 0; i < a.numNode; i++)
                        {
                            if (!a.getMC(i) && !a.getDTD(i) && a.currentM(i) < 4)
                            {
                                if (a.l[i] != 0 || a.d[i] != 0 || a.w[i] != 0)
                                {
                                    a.setDTD(i);
                                    temp.Add(a.sumF1() + tong);
                                    viTriCay.Add(j);
                                    viTriDatTrongCay.Add(i);
                                    a.refresh();
                                }
                            }
                        }
                    }
                    int vitri = findMinPos(temp);
                    if (vitri == -1)
                    {
                        break;
                    }
                    if (temp[vitri] > F_tong)
                    {
                        break;
                    }
                    else
                    {
                        F_last = F_tong;      // F(nMC, nDTD-1,0)
                        F_tong = temp[vitri]; // F(nMC, nDTD, 0)
                    }
                    // set lai vi tri DTD trong cay
                    set[viTriCay[vitri]].setLastDTD(viTriDatTrongCay[vitri]);
                    set[viTriCay[vitri]].refresh();
                    // Neu F_underbound > F_best thi ket thuc // SUA
                    F_underbound = F_tong - (F_last - F_tong) * (MaxDTD - nDTD); // F_underbound = F(N1, x, 0) - (F(N1, x-1, 0) - F(N1, x, 0)) *(N2 - x)
                    if (F_underbound > F_best)
                    {
                        Console.WriteLine("Cut");
                        break;
                    }
                    Console.WriteLine(F_best.ToString() + "," + F_tong.ToString() + "," + F_underbound.ToString() + "," + nMC.ToString() + "," + nDTD.ToString() + ", 0");
                    if (F_tong < F_best)
                    {
                        F_best   = F_tong;
                        best_pos = F.currentLength();
                    }
                    // Them F(N1, N2, 0) vao N2 =1...N2_max;
                    F.Add(nMC, nDTD, 0, F_tong, vtMC, Clone(vtDTD, new int[] { viTriCay[vitri], viTriDatTrongCay[vitri] }), vtDB);
                    vtDTD.Add(new int[] { viTriCay[vitri], viTriDatTrongCay[vitri] }); // them best hien tai vao vtDTD
                }
            }
            for (int nMC = 1; nMC <= MaxMC; nMC++)
            {
                // voi moi N1, N2 = 1...N2_max, N2_max = (chiPhiDauTu - so MC * Pr)/Ps;
                int MaxDTD = (int)((chiPhiDauTu - nMC * Pr) / Ps);
                vtMC = F.getMC_position(nMC, 0, 0); // Lay vi tri cac may cat cua truong hop F(nMC, 0, 0)
                // Neu khong tim duoc vtMC , ket thuc vong lap
                if (vtMC.Count == 0)
                {
                    break;
                }
                for (int nDTD = 1; nDTD <= MaxDTD; nDTD++)
                {
                    // so den bao toi da N3_max;
                    int MaxDB = (int)((chiPhiDauTu - nMC * Pr - nDTD * Ps) / Pf);
                    vtDTD = F.getDTD_position(nMC, nDTD, 0);
                    if (vtDTD.Count == 0)
                    {
                        break;
                    }
                    F_tong = F.getF(nMC, nDTD, 0);
                    for (int nDB = 1; nDB <= MaxDB; nDB++)
                    {
                        List <double> temp             = new List <double>();
                        List <int>    viTriDatTrongCay = new List <int>();
                        List <int>    viTriCay         = new List <int>();
                        for (int j = 0; j < set.Count; j++)
                        {
                            SearchPosition a    = set[j];
                            double         tong = 0;
                            for (int k = 0; k < set.Count; k++)
                            {
                                if (k != j)
                                {
                                    tong += set[k].sumF2();
                                }
                            }
                            for (int i = 0; i < a.numNode; i++)
                            {
                                if (a.l[i] != 0 || a.d[i] != 0 || a.w[i] != 0)
                                {
                                    if (!a.getMC(i) && !a.getDTD(i) && !a.getDB(i))
                                    {
                                        a.setDB(i);
                                        temp.Add(a.sumF2() + tong);
                                        viTriCay.Add(j);
                                        viTriDatTrongCay.Add(i);
                                        a.refresh();
                                    }
                                }
                            }
                        }
                        int vitri = findMinPos(temp);
                        if (vitri == -1)
                        {
                            break;
                        }
                        if (temp[vitri] > F_tong)
                        {
                            break;
                        }
                        else
                        {
                            F_last = F_tong;
                            F_tong = temp[vitri];
                        }
                        //cap nhat
                        set[viTriCay[vitri]].setLastDB(viTriDatTrongCay[vitri]);
                        set[viTriCay[vitri]].refresh();
                        // F_underbound
                        F_underbound = F_tong - (F_last - F_tong) * (MaxDB - nDB);
                        if (F_underbound > F_best)
                        {
                            Console.WriteLine("Cut");
                            break;
                        }
                        Console.WriteLine(F_best.ToString() + "," + F_tong.ToString() + "," + F_underbound.ToString() + "," + nMC.ToString() + "," + nDTD.ToString() + "," + nDB.ToString());
                        if (F_tong < F_best)
                        {
                            F_best   = F_tong;
                            best_pos = F.currentLength();
                        }

                        // Them F(N1, N2, 0) vao N2 =1...N2_max;
                        F.Add(nMC, nDTD, nDB, F_tong, vtMC, vtDTD, Clone(vtDB, new int[] { viTriCay[vitri], viTriDatTrongCay[vitri] }));
                        vtDB.Add(new int[] { viTriCay[vitri], viTriDatTrongCay[vitri] }); // them best hien tai vao vDB
                    }
                }
            }
            return(F.getAt(best_pos));
        }
        // Ham chinh
        public void TimViTriThietBi(int sMC, int sDTD, int sDB)
        {
            this.resetTree();
            List <SearchPosition> set = this.search;
            int    dem    = sDB;
            int    soMC   = sMC;
            int    soDTD  = sDTD;
            int    soDB   = dem;
            double F_tong = Double.MaxValue;

            while (soMC > 0)
            {
                List <double> temp             = new List <double>();
                List <int>    viTriDatTrongCay = new List <int>();
                List <int>    viTriCay         = new List <int>();
                for (int j = 0; j < set.Count; j++)
                {
                    SearchPosition a    = set[j];
                    double         tong = 0;
                    for (int k = 0; k < set.Count; k++)
                    {
                        if (k != j)
                        {
                            tong += set[k].sumF1();
                        }
                    }
                    for (int i = 0; i < a.numNode; i++)
                    {
                        if (!a.getMC(i))
                        {
                            if (a.l[i] != 0 || a.d[i] != 0 || a.w[i] != 0)
                            {
                                a.setMC(i);
                                temp.Add(a.sumF1() + tong);
                                viTriCay.Add(j);
                                viTriDatTrongCay.Add(i);
                                a.refresh();
                            }
                        }
                    }
                }
                int vitri = findMinPos(temp);
                if (vitri == -1)
                {
                    break;
                }
                if (temp[vitri] > F_tong)
                {
                    break;
                }
                else
                {
                    F_tong = temp[vitri];
                }
                set[viTriCay[vitri]].setLastMC(viTriDatTrongCay[vitri]);
                set[viTriCay[vitri]].refresh();
                soMC -= 1;
            }
            while (soDTD > 0)
            {
                List <double> temp             = new List <double>();
                List <int>    viTriDatTrongCay = new List <int>();
                List <int>    viTriCay         = new List <int>();
                for (int j = 0; j < set.Count; j++)
                {
                    SearchPosition a    = set[j];
                    double         tong = 0;
                    for (int k = 0; k < set.Count; k++)
                    {
                        if (k != j)
                        {
                            tong += set[k].sumF1();
                        }
                    }
                    for (int i = 0; i < a.numNode; i++)
                    {
                        if (!a.getMC(i) && !a.getDTD(i) && a.currentM(i) < 4)
                        {
                            if (a.l[i] != 0 || a.d[i] != 0 || a.w[i] != 0)
                            {
                                a.setDTD(i);
                                temp.Add(a.sumF1() + tong);
                                viTriCay.Add(j);
                                viTriDatTrongCay.Add(i);
                                a.refresh();
                            }
                        }
                    }
                }
                int vitri = findMinPos(temp);
                if (vitri == -1)
                {
                    break;
                }
                if (temp[vitri] > F_tong)
                {
                    break;
                }
                else
                {
                    F_tong = temp[vitri];
                }
                set[viTriCay[vitri]].setLastDTD(viTriDatTrongCay[vitri]);
                set[viTriCay[vitri]].refresh();
                soDTD -= 1;
            }
            while (soDB > 0)
            {
                List <double> temp             = new List <double>();
                List <int>    viTriDatTrongCay = new List <int>();
                List <int>    viTriCay         = new List <int>();
                for (int j = 0; j < set.Count; j++)
                {
                    SearchPosition a    = set[j];
                    double         tong = 0;
                    for (int k = 0; k < set.Count; k++)
                    {
                        if (k != j)
                        {
                            tong += set[k].sumF2();
                        }
                    }
                    for (int i = 0; i < a.numNode; i++)
                    {
                        if (a.l[i] != 0 || a.d[i] != 0 || a.w[i] != 0)
                        {
                            if (!a.getMC(i) && !a.getDTD(i) && !a.getDB(i))
                            {
                                a.setDB(i);
                                temp.Add(a.sumF2() + tong);
                                viTriCay.Add(j);
                                viTriDatTrongCay.Add(i);
                                a.refresh();
                            }
                        }
                    }
                }
                int vitri = findMinPos(temp);
                if (vitri == -1)
                {
                    break;
                }
                if (temp[vitri] > F_tong)
                {
                    break;
                }
                else
                {
                    F_tong = temp[vitri];
                }
                set[viTriCay[vitri]].setLastDB(viTriDatTrongCay[vitri]);
                set[viTriCay[vitri]].refresh();
                soDB -= 1;
            }
            this.current_F = F_tong;
            tapMC.Clear();
            tapMC_toaDo.Clear();
            tapDTD.Clear();
            tapDTD_toaDo.Clear();
            tapDB.Clear();
            tapDB_toaDo.Clear();
            for (int i = 0; i < parent.Count; i++)
            {
                for (int j = 1; j < parent[i].Count; j++)
                {
                    if (search[i].mc[j])
                    {
                        tapMC.Add(c.cay_maCot[i][j][1]);
                        tapMC_toaDo.Add(c.cay_toaDo[i][j][1]);
                    }
                    else if (search[i].dtd[j])
                    {
                        tapDTD.Add(c.cay_maCot[i][j][1]);
                        tapDTD_toaDo.Add(c.cay_toaDo[i][j][1]);
                    }
                    else if (search[i].db[j])
                    {
                        tapDB.Add(c.cay_maCot[i][j][1]);
                        tapDB_toaDo.Add(c.cay_toaDo[i][j][1]);
                    }
                }
            }
        }