我需要为每个时间表分配频道。可以存在与为客户分配的通道数一样多的并发事件。即如果客户被分配了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一个用于频道,另一个用于evets,但是无法实现并且复杂性非常高。如何实现这个逻辑?
伪代码:
for each channel
{
foreach existing events
{
if(sametime && same channel)
{
go for next channel
}
break;
}
assign current channel to new event
}
当我尝试创建第3个事件时失败。
答案 0 :(得分:1)
您可以循环浏览事件以将频道分配给事件,请查看下面的伪代码:
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;
}
}
}
答案 1 :(得分:0)
你必须产生所有可能性,并选择最好的。
这是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
所有事件都适合。
所以你必须以某种方式做回溯。
答案 2 :(得分:0)
看起来有点类似于车辆路线问题。通道与车辆相同,事件就像有向非循环图中的节点,边缘从一个事件传递到另一个事件,当且仅当第一个事件比第二个事件开始时更早结束。
您应该能够找到解决此问题的公开算法。
答案 3 :(得分:0)
我修复了代码中的一些问题。我认为现在应该可行了
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;
}
}
}
}