如何在C#中实现以下逻辑?
我需要为每个时间表分配频道。并发事件的数量与为客户分配的通道数量相同。也就是说,如果为客户分配了3个通道,那么他可以有3个并发事件。如果某个通道已分配给某个事件,则不能将同一通道分配给属于同一时间的另一个事件,但如果时间不同,则可以将同一通道分配给另一个事件 通道表如何在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
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),请发布您迄今为止编写的代码。人们通常不喜欢只为您编写代码。事实上,这是一个工作描述,而不是一个问题。当您急切地(向第一个免费频道)分配事件时,您试图传达什么,算法的结果取决于您添加事件的顺序。您可能会遇到这样的情况,即如果您以不同的顺序处理事件,您可以将它们放入可用的通道中,但由于您以这种顺序处理事件,因此有些事件将无法放入任何位置。