用冷却时间优化动作顺序的算法

时间:2013-03-21 20:59:20

标签: algorithm sorting optimization

我可以从“行动”列表中选择每秒执行一次。列表中的每个动作都有一个表示它值多少的数值,还有一个代表其“冷却时间”的值 - 我再次使用该动作之前必须等待的秒数。列表可能如下所示:

  • 动作A的值为1,冷却时间为2秒
  • 动作B的值为1.5,冷却时间为3秒
  • 动作C的值为2,冷却时间为5秒
  • 动作D的值为3,冷却时间为10秒

所以在这种情况下,订单ABA的总值为(1 + 1.5 + 1)= 3.5,这是可以接受的,因为A的首次使用发生在1秒,A的最终使用发生在3秒,然后这两者之间的差异大于或等于A的冷却时间,为2秒。 AAB的命令不起作用,因为你只做了一秒钟,而不是冷却时间。

我的问题是尝试优化使用操作的顺序,最大化一定数量的操作的总价值。显然,如果你只使用一个动作,最佳顺序是做动作D,结果总值为3.两个动作的最大值来自做CD或DC,结果总值为5。当您执行10或20或100个操作时,会变得更复杂。我找不到一种方法来优化动作的顺序而不强制它,这使得复杂性成为指向要优化顺序的动作总数的指数。在过去大约15次之后,这变得不可能。

那么,有没有办法找到最简单的时间而不那么复杂?这个问题有没有被研究过?我想可能会有某种加权图形类型的算法,但我不知道它是如何工作的,更不用说如何实现它了。

很抱歉,如果这让人感到困惑 - 从概念上来说这有点奇怪,我找不到更好的方法来构建它。

3 个答案:

答案 0 :(得分:3)

编辑:这是使用高度修改的Dijkstra算法的正确解决方案:

Dijkstra算法用于找到最短路径,给定一个地图(图摘要),这是一系列节点(通常是位置,但是对于这个例子,假设它们是动作),它们是相互连接的弧(在这种情况下,代替距离,每个弧将具有'值')

这是本质上的结构。

Graph{//in most implementations these are not Arrays, but Maps. Honestly, for your needs you don't a graph, just nodes and arcs... this is just used to keep track of them.
node[] nodes;
arc[] arcs;
}
Node{//this represents an action
arc[] options;//for this implementation, this will always be a list of all possible Actions to use.
float value;//Action value
}
Arc{
node start;//the last action used
node end;//the action after that
dist=1;//1 second
}

我们可以使用此数据类型来制作所有可行选项的映射,以获得最佳解决方案,基于查看每个路径的最终总计。因此,您寻找模式的前景越多,就越有可能找到非常优化的路径。

地图上每一段道路都有一个距离,代表它的价值,而道路上的每一站都是一秒钟的标记,因为这是决定去哪里的时间(对此采取何种行动)执行)接下来。  为简单起见,我们假设A和B是唯一可行的选择。 na意味着没有行动,因为没有行动可用。 如果您旅行4秒钟(数量越大,结果越好),您的选择就是......

A->na->A->na->A
B->na->na->B->na
A->B->A->na->B
B->A->na->B->A
...

还有更多,但我已经知道最佳路径是B-> A-> na-> B-> A,因为它的值是最高的。因此,用于处理这种动作组合的已建立的最佳模式是(至少在分析它4秒之后)B-> A-> na-> B-> A  这实际上是一个非常简单的递归算法。

    /*
     cur is the current action that you are at, it is a Node. In this example, every other action is seen as a viable option, so it's as if every 'place' on the map has a path going to every other path.
     numLeft is the amount of seconds left to run the simulation. The higher the initial value, the more desirable the results.

This won't work as written, but will give you a good idea of how the algorithm works.
*/
function getOptimal(cur,numLeft,path){
  if(numLeft==0){
    var emptyNode;//let's say, an empty node wiht a value of 0.
    return emptyNode;
  }
  var best=path;
  path.add(cur);
  for(var i=0;i<cur.options.length;i++){
    var opt=cur.options[i];//this is a COPY
    if(opt.timeCooled<opt.cooldown){
      continue;
    }
    for(var i2=0;i2<opt.length;i2++){
      opt[i2].timeCooled+=1;//everything below this in the loop is as if it is one second ahead
    }
    var potential=getOptimal(opt[i],numLeft-1,best);
    if(getTotal(potential)>getTotal(cur)){best.add(potential);}//if it makes it better, use it! getTotal will sum up the values of an array of nodes(actions)
  }
  return best;
}
function getOptimalExample(){
  log(getOptimal(someNode,4,someEmptyArrayOfNodes));//someNode will be A or B
}

结束编辑。

我对这个问题感到有些困惑,但是......

如果您的动作数量有限,那就是它,那么总是选择具有最大值的动作,除非尚未达到冷却时间。

听起来你想要这样的东西(伪代码):

function getOptimal(){
var a=[A,B,C,D];//A,B,C, and D are actions
a.sort()//(just pseudocode. Sort the array items by how much value they have.)
var theBest=null;
for(var i=0;i<a.length;++i){//find which action is the most valuable
     if(a[i].timeSinceLastUsed<a[i].cooldown){
        theBest=a[i];
        for(...){//now just loop through, and add time to each OTHER Action for their timeSinceLastUsed...
             //...
         }//That way, some previously used, but more valuable actions will be freed up again.
        break;
    }//because a is worth the most, and you can use it now, so why not?
}
}

答案 1 :(得分:1)

编辑:在重新阅读您的问题后,我发现需要调整加权调度算法以适合您的问题陈述;在我们的例子中,我们只想从集合中取出那些与我们选择的动作类相匹配的重叠动作,以及那些从同一时间点开始的动作。 IE如果我们选择a1,我们希望从集合中移除a2b1,而不是b2

这看起来非常类似于深度in this pdf中讨论的加权调度问题。本质上,权重是你的动作的值,间隔是(starttime,starttime + cooldown)。可以记忆动态编程解决方案,使其在O(nlogn)时间内运行。唯一困难的部分是修改你的问题,使它看起来像加权区间问题,这使我们可以利用预定的解决方案。

因为您的间隔没有设置开始和结束时间(IE可以选择何时开始某个操作),我建议在假设一些设定时间范围的情况下枚举所有给定操作的所有可能的开始时间,然后使用这些动态编程解决方案的静态开始/结束时间。假设你只能在一整秒内开始一个动作,你可以为间隔(0-2,1-3,2-4,...)运行动作A,为(0-3,1-4,2)动作B -5,...),行为C为间隔(0-5,1-6,2-7,...)等。然后你可以使用联合动作的集合来获得看起来像原始加权的问题空间间隔问题:

|---1---2---3---4---5---6---7---| time
|{--a1--}-----------------------| v=1
|---{--a2---}-------------------| v=1
|-------{--a3---}---------------| v=1
|{----b1----}-------------------| v=1.5
|---{----b2-----}---------------| v=1.5
|-------{----b3-----}-----------| v=1.5
|{--------c1--------}-----------| v=2
|---{--------c2---------}-------| v=2
|-------{-------c3----------}---| v=2
etc... 

答案 2 :(得分:0)

始终选择值得最多的可用操作。

相关问题