下面的逻辑如何用C#实现?

发布于 2024-10-31 02:12:42 字数 851 浏览 0 评论 0原文

我需要为每个时间表分配频道。并发事件的数量可以与为客户分配的通道数量一样多。即,如果为客户分配了 3 个通道,那么他可以有 3 个并发事件。如果将一个通道分配给一个事件,则同一通道不能分配给同一时间的另一个事件,但如果时间不同,则可以将同一通道分配给另一个事件。

Channel Table

ID Name
1  Name1
2  Name2
3  Name3

Event Table

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 一个用于通道,另一个用于事件,但无法实现,并且复杂性非常高。这个逻辑如何实现呢?

伪代码:

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

当我尝试创建第三个事件时,此操作失败。

I need to assign channel for each schedule. There can be as many concurrent events as number of channels allocated for the customer. I.e if the customer is allocated 3 channels then he can have 3 concurrent events. If a channel was allocated to a event then the same channel cannot to allocated to another event that falls under same time but the same channel can be allocate to another event if the time differs.

Channel Table

ID Name
1  Name1
2  Name2
3  Name3

Event Table

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

The above is the expected output.

I tried nested foreachloop one for channel and other for evets, but was not able to achieve and the complexity is really high. How to achieve this logic?

Pseudo Code:

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

This fail when I try to create 3rd event.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

葬心 2024-11-07 02:12:42

您可以循环遍历事件以将通道分配给事件,请查看下面的伪代码:

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;
        } 
    }
}

You can rather loop through events for assigning channels to event, check out below pseudo code:

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;
        } 
    }
}
策马西风 2024-11-07 02:12:42

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

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

Looks somewhat similar to Vehicle Routing Problem to me. Channels are the same as vehicles and events are like nodes in a directed acyclic graph with edges leading from one event to another if and only if the first event finishes earlier than the second one starts.

You should be able to find publicly available algorithms for solving this problem.

花开半夏魅人心 2024-11-07 02:12:42

你必须产生所有的可能性,并选择最好的。

这是 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

并且所有事件都适合。

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

You have to generate all possibilities, and choose the best.

It is NP-complete problem, so there's no way to do it both fast and correct - either you do it fast by some heuristic, but then you don't know if it really did the best job, or you do it slow, and i mean slow, but you are sure the result is optimal.

Depends on the size of your data.

EDIT:
Example to demonstrate, that just assigning events to the first free channel won't always work.

We have 3 channels:
Ch1, Ch2, Ch3

We have to place 6 events:

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

If you just assign to the first free place you'll end up with:

Ch1: E1-2, E4
Ch2: E1-3, E4
Ch3: E1-3
and no place for E3-4

If you assigned them in different order, you'll get

Ch1: E1-2, E3-4
Ch2: E1-3, E4
Ch3: E1-3, E4

And all the events would fit.

So you have to do backtracing somehow.

别把无礼当个性 2024-11-07 02:12:42

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

  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;
            }

        }

    }
}

I fixed some problems in the code. I think it should work now

  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;
            }

        }

    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文