Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用多个重叠可能性的两个列表的一对一匹配算法_C#_Algorithm_Sorting - Fatal编程技术网

C# 使用多个重叠可能性的两个列表的一对一匹配算法

C# 使用多个重叠可能性的两个列表的一对一匹配算法,c#,algorithm,sorting,C#,Algorithm,Sorting,这是一个真正的挑战: 我有一份家庭名单和一份帮手名单。每个家庭和每个帮手都有各自需要帮助或可以提供帮助的时间段 举例说明: Family 1: 11:00 - 12:30 Family 2: 13:00 - 18:00 Family 3: 8:15 - 9:30 Helper 1: 14:30 - 16:30 Helper 2: 17:00 - 19:30 Helper 3: 16:45 - 17:45 Helper 4: 17:00 - 18:00 这些条目的数量可能相等,也可能不相等;它

这是一个真正的挑战:

我有一份家庭名单和一份帮手名单。每个家庭和每个帮手都有各自需要帮助或可以提供帮助的时间段

举例说明:

Family 1: 11:00 - 12:30
Family 2: 13:00 - 18:00
Family 3: 8:15 - 9:30

Helper 1: 14:30 - 16:30
Helper 2: 17:00 - 19:30
Helper 3: 16:45 - 17:45
Helper 4: 17:00 - 18:00
这些条目的数量可能相等,也可能不相等;它们在列表内或列表间可能重叠,也可能不重叠

我想做的是找到一种算法,在助手和家庭之间提供最佳覆盖。这与大多数时间表算法不同,因为它是一种使用潜在多对多的一对一匹配。如果在“族”或“助手”中存在完全匹配的,而没有任何平行条目,则会将其保存并从列表中删除,因为这是该时间段的唯一可能性。 然而,我正在努力寻找下一个基本情况。 我不想使用最大优先法,因为这并不总是最优的;最早完成时间/贪婪算法都不是

如果我知道处理helper条目的顺序(即首先打包哪些条目),那么装箱算法似乎会有所帮助


我一直在为此伤脑筋;尽管研究表明它是NP难的,但我想还是有某种解决方案的。

好吧,我只需要将它们的时间转换成整数形式的分钟,如下所示:

//families[n][start, end]
int[][] families = new int[][] {
    new int[] {660, 780},
    new int[] {780, 1080},
    new int[] {495, 570}
};

//helpers[n][start, end]
int[][] helpers = new int[][] {
    new int[] {870,  990},
    new int[] {1020, 1170},
    new int[] {1005, 1065},
    new int[] {1020, 1080}
};
    //check for the optimal helper
    {
        bool foundOptimalHelper = false;
        for (int k = 0; k < helpers.Length; k++) {
            if (families[i][0] >= helpers[k][0] && families[i][1] <= helpers[k][1]) {

                //check if the helper is occupied
                if (!CheckIfHelperAvable(k, families[i][0], families[i][1]))
                     break;

                foundOptimalHelper = true;
                Console.WriteLine("\thelper {0} is optimal during that time period", k);
                helpersSchedule[k].Add(new int[] { i, families[i][0], families[i][1] });
                break;
            }
        }
        if (foundOptimalHelper)
            continue;
    }
我真的不知道你在寻找什么答案,但我相信这有点像帮助者的时间表。 然后我们需要一种存储日程数据的方法。我们可以通过以下方式实现这一点:

//helpersSchedule[helper][events][Family, start, end]
List<List<int[]>> helpersSchedule = new List<List<int[]>>();
现在我们有了真正的魔法

它将首先尝试找到一个在开始时间可用的助手,然后尝试获得一个具有壁橱开始时间的助手。在剩下的时间里,它将继续调用自己

    void TryToCoverTimePeriod(int family, int timeStart = 0, int timeEnd = 1440)
    {
        List<int[]> helperTimeCoverege = new List<int[]>(); //list of helper with coverege time that start before timeStart
        List<int[]> helperTimeCoveregeSecondary = new List<int[]>(); //list of helper with start time that start after timeStart


        for (int i = 0; i < helpers.Length; i++) {
            if (helpers[i][0] <= timeStart && helpers[i][1] > timeStart) {
                if (CheckIfHelperAvable(i, timeStart, Math.Min(timeEnd, helpers[i][1])))
                    helperTimeCoverege.Add(new int[] { i, Math.Min(timeEnd, helpers[i][1]) - timeStart });
            } else if (helpers[i][1] < timeEnd) {
                if (CheckIfHelperAvable(i, helpers[i][0], Math.Min(timeEnd, helpers[i][1])))
                    helperTimeCoveregeSecondary.Add(new int[] { i, helpers[i][0] });
            }
        }

        int[] bestHelper = new int[] { -1, 0 };

        if (helperTimeCoverege.Count > 0) {
            //get best helper
            foreach (int[] helper in helperTimeCoverege) {
                if (helper[1] > bestHelper[1]) {
                    bestHelper[0] = helper[0];
                    bestHelper[1] = helper[1];
                }
            }

            //setting schedule
            helpersSchedule[bestHelper[0]].Add(new int[] { family, timeStart, timeStart + bestHelper[1] });
            if (timeStart + bestHelper[1] < timeEnd) {
                TryToCoverTimePeriod(family, timeStart + bestHelper[1], timeEnd); //not enough, need more helpers
            }

        } else {
            //get best helper
            foreach (int[] helper in helperTimeCoveregeSecondary) {
                if (helper[1] > bestHelper[1]) {
                    bestHelper[0] = helper[0];
                    bestHelper[1] = helper[1];
                }
            }

            //setting schedule
            helpersSchedule[bestHelper[0]].Add(new int[] { family, bestHelper[1], Math.Min(helpers[bestHelper[0]][1], timeEnd) });
            if (Math.Min(helpers[bestHelper[0]][1], timeEnd) < timeEnd) {
                TryToCoverTimePeriod(family, Math.Min(helpers[bestHelper[0]][1], timeEnd), timeEnd); //not enough, need more helpers
            }

        }

    }
void TryToCoverTimePeriod(int系列,int timeStart=0,int timeEnd=1440)
{
List HELPERTIMECOVERGE=new List();//在timeStart之前开始使用coverege time的帮助程序列表
List helpertimecovergesecondary=new List();//在timeStart之后开始的具有开始时间的帮助程序列表
for(int i=0;i0){
//找最好的帮手
foreach(helperItemOverge中的int[]helper){
if(helper[1]>bestHelper[1]){
最佳助手[0]=助手[0];
最佳助手[1]=助手[1];
}
}
//设定时间表
helpersSchedule[bestHelper[0]]添加(新的int[]{family,timeStart,timeStart+bestHelper[1]});
if(timeStart+bestHelper[1]bestHelper[1]){
最佳助手[0]=助手[0];
最佳助手[1]=助手[1];
}
}
//设定时间表
helpersSchedule[bestHelper[0]].Add(新int[]{family,bestHelper[1],Math.Min(helpers[bestHelper[0]][1],timeEnd)});
if(Math.Min(helpers[bestHelper[0]][1],timeEnd)
要显示数据,请执行以下操作

//display helper's Schedule 
Console.WriteLine("--------------------------------------");
for (int i = 0; i < helpersSchedule.Count; i++) {
    Console.WriteLine("Helper n.{0}:", i);

    foreach (int[] helperEvent in helpersSchedule[i]) {
        //Console.WriteLine("\tfamily n.{0}: {1} - {2}", helperEvent[0], helperEvent[1], helperEvent[2]);
        Console.WriteLine("\tfamily n.{0}: {1:00}:{2:00} - {3:00}:{4:00}", helperEvent[0], helperEvent[1] / 60, helperEvent[1] % 60, helperEvent[2] / 60, helperEvent[2] % 60);
    }
}

Console.ReadKey();
//显示助手的日程安排
Console.WriteLine(“---------------------------------------------”);
for(int i=0;i
结果如下。 这是当前家庭和帮手的最佳解决方案

这是洞的计划,享受吧

class Program
{

    //families[n][start, end]
    static int[][] families = new int[][] {
        new int[] {660, 780},
        new int[] {780, 1080},
        new int[] {495, 570},
    };

    //helpers[n][start, end]
    static int[][] helpers = new int[][] {
        new int[] {870,  990},
        new int[] {1020, 1170},
        new int[] {1005, 1065},
        new int[] {1020, 1080}
    };

    //helpersSchedule[helper][events][Family, start, end]
    static List<List<int[]>> helpersSchedule = new List<List<int[]>>();


    static void Main(string[] args)
    {

        int workTimeStart = 1440;
        int workTimeEnd = 0;

        for (int i = 0; i < helpers.Length; i++) {
            helpersSchedule.Add(new List<int[]>());

            if (helpers[i][0] < workTimeStart)
                workTimeStart = helpers[i][0];
            else if (helpers[i][1] > workTimeEnd)
                workTimeEnd = helpers[i][1];
        }

        for (int i = 0; i < families.Length; i++) {

            //Console.WriteLine("calculating for family n.{0}", i);
            if (workTimeStart > families[i][1] || workTimeEnd < families[i][0]) {
                //Console.WriteLine("\tno helper available during that time period");
                continue;
            }


            /*
            //check for optimal helper
            {
                bool foundOptimalHelper = false;
                for (int k = 0; k < helpers.Length; k++) {
                    if (families[i][0] >= helpers[k][0] && families[i][1] <= helpers[k][1]) {

                        //check if the helper is occupied
                        if (!CheckIfHelperAvable(k, families[i][0], families[i][1]))
                            break;

                        foundOptimalHelper = true;
                        Console.WriteLine("\thelper {0} is optimal during that time period", k);
                        helpersSchedule[k].Add(new int[] { i, families[i][0], families[i][1] });
                        break;
                    }
                }
                if (foundOptimalHelper)
                    continue;
            }
            */

            //cover time
            TryToCoverTimePeriod(i, families[i][0], families[i][1]);

        }


        //display helper's Schedule 
        Console.WriteLine("--------------------------------------");
        for (int i = 0; i < helpersSchedule.Count; i++) {
            Console.WriteLine("Helper n.{0}:", i);

            foreach (int[] helperEvent in helpersSchedule[i]) {
                //Console.WriteLine("\tfamily n.{0}: {1} - {2}", helperEvent[0], helperEvent[1], helperEvent[2]);
                Console.WriteLine("\tfamily n.{0}: {1:00}:{2:00} - {3:00}:{4:00}", helperEvent[0], helperEvent[1] / 60, helperEvent[1] % 60, helperEvent[2] / 60, helperEvent[2] % 60);
            }
        }



        Console.ReadKey();
    }

    static bool CheckIfHelperAvable(int helper, int timeStart = 0, int timeEnd = 1440)
    {

        foreach (int[] helpEvent in helpersSchedule[helper]) {
            if (timeEnd < helpEvent[2] || timeStart > helpEvent[1]) {
                continue;
            } else {
                //helper is occupied during that time period
                return false;
            }
        }

        return true;
    }

    static void TryToCoverTimePeriod(int family, int timeStart = 0, int timeEnd = 1440)
    {
        List<int[]> helperTimeCoverege = new List<int[]>(); //list of helper with coverege time that start before timeStart
        List<int[]> helperTimeCoveregeSecondary = new List<int[]>(); //list of helper with start time that start after timeStart


        for (int i = 0; i < helpers.Length; i++) {
            if (helpers[i][0] <= timeStart && helpers[i][1] > timeStart) {
                if (CheckIfHelperAvable(i, timeStart, Math.Min(timeEnd, helpers[i][1])))
                    helperTimeCoverege.Add(new int[] { i, Math.Min(timeEnd, helpers[i][1]) - timeStart });
            } else if (helpers[i][0] < timeEnd) {
                if (CheckIfHelperAvable(i, helpers[i][0], Math.Min(timeEnd, helpers[i][1])))
                    helperTimeCoveregeSecondary.Add(new int[] { i, helpers[i][0] });
            }
        }


        if (helperTimeCoverege.Count > 0) {
            int[] bestHelper = new int[] { -1, 0 };
            //get best helper
            foreach (int[] helper in helperTimeCoverege) {
                if (helper[1] > bestHelper[1]) {
                    bestHelper[0] = helper[0];
                    bestHelper[1] = helper[1];
                }
            }

            //setting schedule
            helpersSchedule[bestHelper[0]].Add(new int[] { family, timeStart, timeStart + bestHelper[1] });
            if (timeStart + bestHelper[1] < timeEnd) {
                TryToCoverTimePeriod(family, timeStart + bestHelper[1], timeEnd); //not enough, need more helpers
            }

        } else if (helperTimeCoveregeSecondary.Count > 0) {
            int[] bestHelper = new int[] { -1, 1440 };
            //get best helper
            foreach (int[] helper in helperTimeCoveregeSecondary) {
                if (helper[1] < bestHelper[1]) {
                    bestHelper[0] = helper[0];
                    bestHelper[1] = helper[1];
                }
            }

            //setting schedule
            helpersSchedule[bestHelper[0]].Add(new int[] { family, bestHelper[1], Math.Min(helpers[bestHelper[0]][1], timeEnd) });
            if (Math.Min(helpers[bestHelper[0]][1], timeEnd) < timeEnd) {
                TryToCoverTimePeriod(family, Math.Min(helpers[bestHelper[0]][1], timeEnd), timeEnd); //not enough, need more helpers
            }

        }

    }

}
类程序
{
//家庭[开始,结束]
静态int[][]族=新int[][]{
新int[]{660780},
新的int[]{7801080},
新的int[]{495570},
};
//助手[n][开始,结束]
静态int[]helpers=新int[]{
新int[]{870990},
新的int[]{1020,1170},
新的int[]{10051065},
新int[]{10201080}
};
//助手计划[助手][事件][家庭,开始,结束]
静态列表帮助程序Schedule=新列表();
静态void Main(字符串[]参数)
{
int workTimeStart=1440;
int workTimeEnd=0;
for(int i=0;iworkTimeEnd)
workTimeEnd=helpers[i][1];
}
对于(int i=0;ifamilies[i][1]| | workTimeEnd    //cover time
    TryToCoverTimePeriod(i, families[i][0], families[i][1]);

}
    void TryToCoverTimePeriod(int family, int timeStart = 0, int timeEnd = 1440)
    {
        List<int[]> helperTimeCoverege = new List<int[]>(); //list of helper with coverege time that start before timeStart
        List<int[]> helperTimeCoveregeSecondary = new List<int[]>(); //list of helper with start time that start after timeStart


        for (int i = 0; i < helpers.Length; i++) {
            if (helpers[i][0] <= timeStart && helpers[i][1] > timeStart) {
                if (CheckIfHelperAvable(i, timeStart, Math.Min(timeEnd, helpers[i][1])))
                    helperTimeCoverege.Add(new int[] { i, Math.Min(timeEnd, helpers[i][1]) - timeStart });
            } else if (helpers[i][1] < timeEnd) {
                if (CheckIfHelperAvable(i, helpers[i][0], Math.Min(timeEnd, helpers[i][1])))
                    helperTimeCoveregeSecondary.Add(new int[] { i, helpers[i][0] });
            }
        }

        int[] bestHelper = new int[] { -1, 0 };

        if (helperTimeCoverege.Count > 0) {
            //get best helper
            foreach (int[] helper in helperTimeCoverege) {
                if (helper[1] > bestHelper[1]) {
                    bestHelper[0] = helper[0];
                    bestHelper[1] = helper[1];
                }
            }

            //setting schedule
            helpersSchedule[bestHelper[0]].Add(new int[] { family, timeStart, timeStart + bestHelper[1] });
            if (timeStart + bestHelper[1] < timeEnd) {
                TryToCoverTimePeriod(family, timeStart + bestHelper[1], timeEnd); //not enough, need more helpers
            }

        } else {
            //get best helper
            foreach (int[] helper in helperTimeCoveregeSecondary) {
                if (helper[1] > bestHelper[1]) {
                    bestHelper[0] = helper[0];
                    bestHelper[1] = helper[1];
                }
            }

            //setting schedule
            helpersSchedule[bestHelper[0]].Add(new int[] { family, bestHelper[1], Math.Min(helpers[bestHelper[0]][1], timeEnd) });
            if (Math.Min(helpers[bestHelper[0]][1], timeEnd) < timeEnd) {
                TryToCoverTimePeriod(family, Math.Min(helpers[bestHelper[0]][1], timeEnd), timeEnd); //not enough, need more helpers
            }

        }

    }
//display helper's Schedule 
Console.WriteLine("--------------------------------------");
for (int i = 0; i < helpersSchedule.Count; i++) {
    Console.WriteLine("Helper n.{0}:", i);

    foreach (int[] helperEvent in helpersSchedule[i]) {
        //Console.WriteLine("\tfamily n.{0}: {1} - {2}", helperEvent[0], helperEvent[1], helperEvent[2]);
        Console.WriteLine("\tfamily n.{0}: {1:00}:{2:00} - {3:00}:{4:00}", helperEvent[0], helperEvent[1] / 60, helperEvent[1] % 60, helperEvent[2] / 60, helperEvent[2] % 60);
    }
}

Console.ReadKey();
class Program
{

    //families[n][start, end]
    static int[][] families = new int[][] {
        new int[] {660, 780},
        new int[] {780, 1080},
        new int[] {495, 570},
    };

    //helpers[n][start, end]
    static int[][] helpers = new int[][] {
        new int[] {870,  990},
        new int[] {1020, 1170},
        new int[] {1005, 1065},
        new int[] {1020, 1080}
    };

    //helpersSchedule[helper][events][Family, start, end]
    static List<List<int[]>> helpersSchedule = new List<List<int[]>>();


    static void Main(string[] args)
    {

        int workTimeStart = 1440;
        int workTimeEnd = 0;

        for (int i = 0; i < helpers.Length; i++) {
            helpersSchedule.Add(new List<int[]>());

            if (helpers[i][0] < workTimeStart)
                workTimeStart = helpers[i][0];
            else if (helpers[i][1] > workTimeEnd)
                workTimeEnd = helpers[i][1];
        }

        for (int i = 0; i < families.Length; i++) {

            //Console.WriteLine("calculating for family n.{0}", i);
            if (workTimeStart > families[i][1] || workTimeEnd < families[i][0]) {
                //Console.WriteLine("\tno helper available during that time period");
                continue;
            }


            /*
            //check for optimal helper
            {
                bool foundOptimalHelper = false;
                for (int k = 0; k < helpers.Length; k++) {
                    if (families[i][0] >= helpers[k][0] && families[i][1] <= helpers[k][1]) {

                        //check if the helper is occupied
                        if (!CheckIfHelperAvable(k, families[i][0], families[i][1]))
                            break;

                        foundOptimalHelper = true;
                        Console.WriteLine("\thelper {0} is optimal during that time period", k);
                        helpersSchedule[k].Add(new int[] { i, families[i][0], families[i][1] });
                        break;
                    }
                }
                if (foundOptimalHelper)
                    continue;
            }
            */

            //cover time
            TryToCoverTimePeriod(i, families[i][0], families[i][1]);

        }


        //display helper's Schedule 
        Console.WriteLine("--------------------------------------");
        for (int i = 0; i < helpersSchedule.Count; i++) {
            Console.WriteLine("Helper n.{0}:", i);

            foreach (int[] helperEvent in helpersSchedule[i]) {
                //Console.WriteLine("\tfamily n.{0}: {1} - {2}", helperEvent[0], helperEvent[1], helperEvent[2]);
                Console.WriteLine("\tfamily n.{0}: {1:00}:{2:00} - {3:00}:{4:00}", helperEvent[0], helperEvent[1] / 60, helperEvent[1] % 60, helperEvent[2] / 60, helperEvent[2] % 60);
            }
        }



        Console.ReadKey();
    }

    static bool CheckIfHelperAvable(int helper, int timeStart = 0, int timeEnd = 1440)
    {

        foreach (int[] helpEvent in helpersSchedule[helper]) {
            if (timeEnd < helpEvent[2] || timeStart > helpEvent[1]) {
                continue;
            } else {
                //helper is occupied during that time period
                return false;
            }
        }

        return true;
    }

    static void TryToCoverTimePeriod(int family, int timeStart = 0, int timeEnd = 1440)
    {
        List<int[]> helperTimeCoverege = new List<int[]>(); //list of helper with coverege time that start before timeStart
        List<int[]> helperTimeCoveregeSecondary = new List<int[]>(); //list of helper with start time that start after timeStart


        for (int i = 0; i < helpers.Length; i++) {
            if (helpers[i][0] <= timeStart && helpers[i][1] > timeStart) {
                if (CheckIfHelperAvable(i, timeStart, Math.Min(timeEnd, helpers[i][1])))
                    helperTimeCoverege.Add(new int[] { i, Math.Min(timeEnd, helpers[i][1]) - timeStart });
            } else if (helpers[i][0] < timeEnd) {
                if (CheckIfHelperAvable(i, helpers[i][0], Math.Min(timeEnd, helpers[i][1])))
                    helperTimeCoveregeSecondary.Add(new int[] { i, helpers[i][0] });
            }
        }


        if (helperTimeCoverege.Count > 0) {
            int[] bestHelper = new int[] { -1, 0 };
            //get best helper
            foreach (int[] helper in helperTimeCoverege) {
                if (helper[1] > bestHelper[1]) {
                    bestHelper[0] = helper[0];
                    bestHelper[1] = helper[1];
                }
            }

            //setting schedule
            helpersSchedule[bestHelper[0]].Add(new int[] { family, timeStart, timeStart + bestHelper[1] });
            if (timeStart + bestHelper[1] < timeEnd) {
                TryToCoverTimePeriod(family, timeStart + bestHelper[1], timeEnd); //not enough, need more helpers
            }

        } else if (helperTimeCoveregeSecondary.Count > 0) {
            int[] bestHelper = new int[] { -1, 1440 };
            //get best helper
            foreach (int[] helper in helperTimeCoveregeSecondary) {
                if (helper[1] < bestHelper[1]) {
                    bestHelper[0] = helper[0];
                    bestHelper[1] = helper[1];
                }
            }

            //setting schedule
            helpersSchedule[bestHelper[0]].Add(new int[] { family, bestHelper[1], Math.Min(helpers[bestHelper[0]][1], timeEnd) });
            if (Math.Min(helpers[bestHelper[0]][1], timeEnd) < timeEnd) {
                TryToCoverTimePeriod(family, Math.Min(helpers[bestHelper[0]][1], timeEnd), timeEnd); //not enough, need more helpers
            }

        }

    }

}