Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.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_Optimization_Backtracking_Knapsack Problem - Fatal编程技术网

C# (动态规划)如何通过会议列表最大化房间利用率?

C# (动态规划)如何通过会议列表最大化房间利用率?,c#,algorithm,optimization,backtracking,knapsack-problem,C#,Algorithm,Optimization,Backtracking,Knapsack Problem,我正在用动态规划来解决这个问题 问题: 提供会议室和间隔列表(代表会议),例如: 间隔1:1.00-2.00 间隔2:2.00-4.00 间隔3:14.00-16.00 ... 等等 问题: 如何安排会议以最大限度地提高会议室的利用率,以及任何会议都不应相互重叠 尝试解决方案 下面是我在C#中的初步尝试(知道这是一个带约束的改进背包问题)。然而,我很难得到正确的结果 bool ContainsOverlapped(List<Interval> list) {

我正在用动态规划来解决这个问题

问题: 提供会议室和间隔列表(代表会议),例如:

  • 间隔1:1.00-2.00
  • 间隔2:2.00-4.00
  • 间隔3:14.00-16.00 ... 等等
问题: 如何安排会议以最大限度地提高会议室的利用率,以及任何会议都不应相互重叠

尝试解决方案 下面是我在C#中的初步尝试(知道这是一个带约束的改进背包问题)。然而,我很难得到正确的结果

bool ContainsOverlapped(List<Interval> list)
    {
        var sortedList = list.OrderBy(x => x.Start).ToList();
        for (int i = 0; i < sortedList.Count; i++)
        {
            for (int j = i + 1; j < sortedList.Count; j++)
            {
                if (sortedList[i].IsOverlap(sortedList[j]))
                    return true;
            }
        }
        return false;
    }
    public bool Optimize(List<Interval> intervals, int limit, List<Interval> itemSoFar){
        if (intervals == null || intervals.Count == 0)
            return true; //no more choice

        if (Sum(itemSoFar) > limit) //over limit
            return false;

        var arrInterval = intervals.ToArray();

        //try all choices
        for (int i = 0; i < arrInterval.Length; i++){
            List<Interval> remaining = new List<Interval>();
            for (int j = i + 1; j < arrInterval.Length; j++) { 
                remaining.Add(arrInterval[j]);
            }

            var partialChoice = new List<Interval>();
            partialChoice.AddRange(itemSoFar);
            partialChoice.Add(arrInterval[i]);

            //should not schedule overlap
            if (ContainsOverlapped(partialChoice))
                partialChoice.Remove(arrInterval[i]);

            if (Optimize(remaining, limit, partialChoice))
                return true;
            else
                partialChoice.Remove(arrInterval[i]); //undo
        }

        //try all solution
        return false;
    }


public class Interval
{
    public bool IsOverlap(Interval other)
    {
        return (other.Start < this.Start && this.Start < other.End) || //other < this
                (this.Start < other.Start && other.End < this.End) || // this covers other
                (other.Start < this.Start && this.End < other.End) || // other covers this
                (this.Start < other.Start && other.Start < this.End); //this < other
    }
    public override bool Equals(object obj){
        var i = (Interval)obj;
        return base.Equals(obj) && i.Start == this.Start && i.End == this.End;
    }
    public int Start { get; set; }
    public int End { get; set; }
    public Interval(int start, int end){
        Start = start;
        End = end;
    }
    public int Duration{
        get{
            return End - Start;
        }
    }
}
bool ContainsOverlapped(列表)
{
var sortedList=list.OrderBy(x=>x.Start.ToList();
对于(int i=0;i限制)//超过限制
返回false;
var arrInterval=interval.ToArray();
//尝试所有的选择
for(int i=0;i
编辑1 房间利用率=房间被占用的时间量。抱歉搞混了

编辑2
为简单起见:每个间隔的持续时间是整数,开始/结束时间从整小时(1,2,3..24)开始。

好的方法是创建可以轻松处理的类

首先,我创建了帮助器类,以便轻松地存储间隔

public class FromToDateTime
{
    private DateTime _start;
    public DateTime Start
    {
        get
        {
            return _start;
        }
        set
        {
            _start = value;
        }
    }

    private DateTime _end;
    public DateTime End
    {
        get
        {
            return _end;
        }
        set
        {
            _end = value;
        }
    }

    public FromToDateTime(DateTime start, DateTime end)
    {
        Start = start;
        End = end;
    }
}
然后这里是教室,所有的间隔都在这里,它有方法“addInterval”,如果间隔是确定的,则返回true,如果间隔是被添加的,则返回false

顺便说一句:我这里有一个重叠的检查条件:

公共教室
{
私有列表间隔;
公开列表间隔
{
收到
{
返回间隔;
}
设置
{
_间隔=值;
}
}
公共房间()
{
间隔=新列表();
}
公共bool addInterval(FromToDateTime newInterval)
{
foreach(FromToDate时间间隔,以间隔为单位)
{
if(newInterval.Start
好的方法是创建一个可以轻松处理的类

首先,我创建了帮助器类,以便轻松地存储间隔

public class FromToDateTime
{
    private DateTime _start;
    public DateTime Start
    {
        get
        {
            return _start;
        }
        set
        {
            _start = value;
        }
    }

    private DateTime _end;
    public DateTime End
    {
        get
        {
            return _end;
        }
        set
        {
            _end = value;
        }
    }

    public FromToDateTime(DateTime start, DateTime end)
    {
        Start = start;
        End = end;
    }
}
然后这里是教室,所有的间隔都在这里,它有方法“addInterval”,如果间隔是确定的,则返回true,如果间隔是被添加的,则返回false

顺便说一句:我这里有一个重叠的检查条件:

公共教室
{
私有列表间隔;
公开列表间隔
{
收到
{
返回间隔;
}
设置
{
_间隔=值;
}
}
公共房间()
{
间隔=新列表();
}
公共bool addInterval(FromToDateTime newInterval)
{
foreach(FromToDate时间间隔,以间隔为单位)
{
if(newInterval.Start
而更一般的问题(如果您有多个会议室)实际上是NP难问题,称为

一教室一维问题的最佳解决方案:
对于一维问题,选择(仍然有效的)最早截止日期首先解决问题

证明:通过归纳,基本子句是无效子句-该算法最佳地解决了零会议的问题

归纳假设是,对于任意数量的
k
任务,算法都能以最佳方式解决问题

步骤:给定
n
会议的问题,选择最早的截止日期,并在选择后删除所有无效会议。让选择的最早截止日期任务为
T

你会得到一个新的p
findOptimal(list<tasks>):
   res = [] //empty list
   sort(list) //according to deadline/meeting end
   while (list.IsEmpty() == false):
        res = res.append(list.first())
        end = list.first().endTime()
        //remove all overlaps with the chosen meeting
        while (list.first().startTine() < end):
              list.removeFirst()
   return res
V[i] = max{ V[j]            | j < i and i->j is an edge, 
            V[k] + value[i] | k < i and there is no edge between i and k }

Base Case V[1] = value[1]
Optimize(n) {
    opt(0) = 0;
    for j = 1 to n-th {
        opt(j) = max(length(j) + opt[p(j)], opt[j-1]);
    }               
}
    namespace CommonProblems.Algorithm.DynamicProgramming {
    public class Scheduler {
        #region init & test
        public List<Event> _events { get; set; }

        public List<Event> Init() {
            if (_events == null) {
                _events = new List<Event>();
                _events.Add(new Event(8, 11));
                _events.Add(new Event(6, 10));
                _events.Add(new Event(5, 9));
                _events.Add(new Event(3, 8));
                _events.Add(new Event(4, 7));
                _events.Add(new Event(0, 6));
                _events.Add(new Event(3, 5));
                _events.Add(new Event(1, 4));
            }

            return _events;
        }

        public void DemoOptimize() {
            this.Init();
            this.DynamicOptimize(this._events);
        }
        #endregion

        #region Dynamic Programming
        public void DynamicOptimize(List<Event> events) {
            events.Add(new Event(0, 0));
            events = events.SortByEndTime();

            int[] eventIndexes = getCompatibleEvent(events);
            int[] utilization = getBestUtilization(events, eventIndexes);
            List<Event> schedule = getOptimizeSchedule(events, events.Count - 1, utilization, eventIndexes);

            foreach (var e in schedule) {
                Console.WriteLine("Event: [{0}- {1}]", e.Start, e.End);
            }
        }

        /*
        Algo to get optimization value:
        1) Sort all events by end time, give each of the an index.
        2) For each event, find p[n] - the latest event (by end time) which does not overlap with it.
        3) Compute the optimization values: choose the best between including/not including the event.

        Optimize(n) {
            opt(0) = 0;
            for j = 1 to n-th {
                opt(j) = max(length(j) + opt[p(j)], opt[j-1]);
            }
            display opt();
        }
        */
        int[] getBestUtilization(List<Event> sortedEvents, int[] compatibleEvents) {
            int[] optimal = new int[sortedEvents.Count];
            int n = optimal.Length;

            optimal[0] = 0;

            for (int j = 1; j < n; j++) {
                var thisEvent = sortedEvents[j];

                //pick between 2 choices:
                optimal[j] = Math.Max(thisEvent.Duration + optimal[compatibleEvents[j]],  //Include this event
                                       optimal[j - 1]);                                   //Not include
            }

            return optimal;
        }

        /* 
        Show the optimized events: 
            sortedEvents: events sorted by end time.
            index: event index to start with.
            optimal: optimal[n] = the optimized schedule at n-th event.
            compatibleEvents: compatibleEvents[n] = the latest event before n-th
         */
        List<Event> getOptimizeSchedule(List<Event> sortedEvents, int index, int[] optimal, int[] compatibleEvents) {
            List<Event> output = new List<Event>();
            if (index == 0) {
                //base case: no more event
                return output;
            }

            //it's better to choose this event
            else if (sortedEvents[index].Duration + optimal[compatibleEvents[index]] >= optimal[index]) {
                output.Add(sortedEvents[index]);

                //recursive go back
                output.AddRange(getOptimizeSchedule(sortedEvents, compatibleEvents[index], optimal, compatibleEvents));
                return output;
            }

            //it's better NOT choose this event
            else {
                output.AddRange(getOptimizeSchedule(sortedEvents, index - 1, optimal, compatibleEvents));
                return output;
            }
        }

        //compatibleEvents[n] = the latest event which do not overlap with n-th.
        int[] getCompatibleEvent(List<Event> sortedEvents) {
            int[] compatibleEvents = new int[sortedEvents.Count];

            for (int i = 0; i < sortedEvents.Count; i++) {
                for (int j = 0; j <= i; j++) {
                    if (!sortedEvents[j].IsOverlap(sortedEvents[i])) {
                        compatibleEvents[i] = j;
                    }
                }
            }
            return compatibleEvents;
        }
        #endregion
    }
    public class Event {
        public int EventId { get; set; }
        public bool IsOverlap(Event other) {
            return !(this.End <= other.Start ||
                    this.Start >= other.End);
        }
        public override bool Equals(object obj) {
            var i = (Event)obj;
            return base.Equals(obj) && i.Start == this.Start && i.End == this.End;
        }
        public int Start { get; set; }
        public int End { get; set; }
        public Event(int start, int end) {
            Start = start;
            End = end;
        }
        public int Duration {
            get {
                return End - Start;
            }
        }
    }
    public static class ListExtension {
        public static bool ContainsOverlapped(this List<Event> list) {
            var sortedList = list.OrderBy(x => x.Start).ToList();
            for (int i = 0; i < sortedList.Count; i++) {
                for (int j = i + 1; j < sortedList.Count; j++) {
                    if (sortedList[i].IsOverlap(sortedList[j]))
                        return true;
                }
            }
            return false;
        }
        public static List<Event> SortByEndTime(this List<Event> events) {
            if (events == null) return new List<Event>();

            return events.OrderBy(x => x.End).ToList();
        }
    }
}