如何在C#中实现以下逻辑?

如何在C#中实现以下逻辑?,c#,asp.net,logic,C#,Asp.net,Logic,我需要为每个时间表分配频道。并发事件的数量与为客户分配的通道数量相同。也就是说,如果为客户分配了3个通道,那么他可以有3个并发事件。如果某个通道已分配给某个事件,则不能将同一通道分配给属于同一时间的另一个事件,但如果时间不同,则可以将同一通道分配给另一个事件 通道表 ID Name 1 Name1 2 Name2 3 Name3 事件表 ID EventName StartTime EndTime ChannelID 1 Event1 11:30AM 12PM 1 2

我需要为每个时间表分配频道。并发事件的数量与为客户分配的通道数量相同。也就是说,如果为客户分配了3个通道,那么他可以有3个并发事件。如果某个通道已分配给某个事件,则不能将同一通道分配给属于同一时间的另一个事件,但如果时间不同,则可以将同一通道分配给另一个事件

通道表

ID Name
1  Name1
2  Name2
3  Name3
事件表

ID EventName StartTime EndTime ChannelID
1  Event1    11:30AM   12PM    1
2  Event2    11:30AM   11:40AM 2
3  Event3    11:40AM   12PM    2
4  Event4    12PM      12:30PM 1 0r 2
5  Event5    11:30AM   12:30PM 3
以上是预期产出

我尝试了嵌套的foreachloop,一个用于channel,另一个用于evets,但未能实现,而且复杂性非常高。如何实现这一逻辑

伪代码:

for each channel
{
    foreach existing events
    {
        if(sametime && same channel)
            {
             go for next channel
            }
        break;
    }
assign current channel to new event
}

当我尝试创建第三个事件时失败。

您必须生成所有可能性,并选择最佳

这是一个NP完全问题,所以没有办法做到既快又正确——要么你通过一些启发式快速地完成,但你不知道它是否真的做得最好,要么你做得慢,我的意思是慢,但你肯定结果是最优的

取决于数据的大小

编辑: 例如,仅将事件分配给第一个空闲通道并不总是有效

我们有3个频道: Ch1,Ch2,Ch3

我们必须安排6项活动:

E1-2 - starts at 1:00 ends at 2:59
E1-3 - starts at 1:00 ends at 3:59
E1-3 - starts at 1:00 ends at 3:59
E4 - starts at 4:00 ends at 4:59
E4 - starts at 4:00 ends at 4:59
E3-4 - starts at 3:00 ends at 4:59
如果您只分配到第一个空闲位置,您将得到:

Ch1: E1-2, E4
Ch2: E1-3, E4
Ch3: E1-3
and no place for E3-4
如果您按不同的顺序分配它们,您将得到

Ch1: E1-2, E3-4
Ch2: E1-3, E4
Ch3: E1-3, E4
所有的活动都适合


所以你必须以某种方式进行回溯。

在我看来有点类似于车辆路径问题。通道与车辆相同,事件类似于有向无环图中的节点,当且仅当第一个事件的结束时间早于第二个事件的开始时间时,边从一个事件指向另一个事件


您应该能够找到解决此问题的公开可用算法。

您可以通过循环事件来为事件分配通道,请查看以下伪代码:

foreach events 
{ 
    foreach channels 
    { 
        if currentChannel is assigned 
        { 
            foreach assignedEvents 
            { 
                if assignedTime = currentEventTime 
                    go to next Channel (continue)
            } 
            currentEvent.Channel = currentChannel 
            break;
        } 
        else 
        { 
            currentEvent.Channel = currentChannel 
            break;
        } 
    }
}

我修复了代码中的一些问题。我想现在应该行了

  using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

namespace ChannelAllocator
{

    class Program
    {
        const int _numberOfChannels = 10;
        static void Main(string[] args)
        {
            Dictionary<int, List<TimeSlot>> occupiedChannels = new Dictionary<int, List<TimeSlot>>();

            for (int i = 1; i <= _numberOfChannels; i++)
            {

                occupiedChannels.Add(i, new List<TimeSlot>());
            }

            /** Example **/
            TimeSpan start = DateTime.Now.AddHours(-1.0).TimeOfDay;
            TimeSpan end = DateTime.Now.TimeOfDay;
            AssignChannel(occupiedChannels, ref start, ref end);           

        }

        private static bool AssignChannel(Dictionary<int, List<TimeSlot>> occupiedChannels, ref TimeSpan start, ref TimeSpan end)
        {
            List<int> channels = occupiedChannels.Keys.ToList();
            if (start >= end )
                return false;
            foreach (var item in channels)
            {
                List<TimeSlot> slots = occupiedChannels[item];
                if (slots.Count == 0)
                {
                    occupiedChannels[item].Add(new TimeSlot(start, end));
                    return true;

                }
                else
                {
                    bool available = false ;
                    foreach (var slot in slots)
                    {
                        TimeSpan channelStartTime = slot.StartTime;
                        TimeSpan channelEndTime = slot.EndTime;

                        if (start >= channelStartTime && end <= channelEndTime ||
                            start <= channelStartTime && end <= channelEndTime && end >= channelStartTime
                            || end >= channelEndTime && start >= channelStartTime && start <= channelEndTime)
                        {
                            available = false;
                            break;    
                        }
                        else { 
                            available = true; 
                        }
                    }
                    if (available)
                    {
                        occupiedChannels[item].Add(new TimeSlot(start, end));
                        return true;
                    }

                }
            }
            return false;
        }

        private class TimeSlot
        {
            public TimeSpan StartTime;
            public TimeSpan EndTime;
            public TimeSlot(TimeSpan start, TimeSpan end)
            {
                StartTime = start;
                EndTime = end;
            }

        }

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
命名空间通道分配器
{
班级计划
{
const int_numberOfChannels=10;
静态void Main(字符串[]参数)
{
Dictionary OccupiedChannel=新字典();
for(int i=1;i=end)
返回false;
foreach(通道中的var项)
{
列表插槽=占用的频道[项目];
如果(slots.Count==0)
{
占用的频道[项目]。添加(新时隙(开始、结束));
返回true;
}
其他的
{
bool available=false;
foreach(插槽中的var插槽)
{
TimeSpan channelStartTime=slot.StartTime;
TimeSpan channelEndTime=slot.EndTime;

如果(开始>=channelStartTime&&end=channelStartTime&&start),请发布您迄今为止编写的代码。人们通常不喜欢只为您编写代码。事实上,这是一个工作描述,而不是一个问题。当您急切地(向第一个免费频道)分配事件时,您试图传达什么,算法的结果取决于您添加事件的顺序。您可能会遇到这样的情况,即如果您以不同的顺序处理事件,您可以将它们放入可用的通道中,但由于您以这种顺序处理事件,因此有些事件将无法放入任何位置。