5

「アクション」のリストから選択して、1 秒に 1 回実行できます。リストの各アクションには、その価値を表す数値と、「クールダウン」を表す値 (そのアクションを再度使用するまでに待機する必要がある秒数) があります。リストは次のようになります。

  • アクション A の値は 1 で、クールダウンは 2 秒です
  • アクション B の値は 1.5 で、クールダウンは 3 秒です
  • アクション C の値は 2 で、クールダウンは 5 秒です
  • アクション D の値は 3 で、クールダウンは 10 秒です

したがって、この状況では、オーダー ABA の合計値は (1+1.5+1) = 3.5 になり、A の最初の使用が 1 秒で発生し、A の最後の使用が 3 秒で発生するため、許容されます。そして、それらの 2 つの差が A のクールダウン 2 秒以上である。クールダウンよりもわずか 1 秒間隔で A を実行するため、AAB の順序は機能しません。

私の問題は、アクションが使用される順序を最適化し、特定の数のアクションの合計値を最大化しようとすることです。明らかに、1 つのアクションのみを使用する場合の最適な順序は、アクション D を実行することで、合計値は 3 になります。2 つのアクションの最大値は、CD または DC を実行することで得られ、合計値は 5 になります。合計10回、20回、または100回のアクションを実行すると、より複雑になります. アクションの順序をブルートフォースせずに最適化する方法を見つけることができません。これにより、順序を最適化するアクションの総数が指数関数的に複雑になります。それは合計約15を超えると不可能になります。

では、複雑さを軽減して最適な時間を見つける方法はありますか? この問題は研究されたことがありますか? これで機能するある種の重み付きグラフタイプのアルゴリズムがあると思いますが、実装方法は言うまでもなく、それがどのように機能するかわかりません。

これが混乱している場合は申し訳ありません-概念的には奇妙であり、それを組み立てるより良い方法を見つけることができませんでした.

4

3 に答える 3

3

編集:高度に変更されたダイクストラのアルゴリズムを使用した適切なソリューションは次のとおりです。

ダイクストラのアルゴリズムを使用して、一連のノード(通常は場所ですが、この例ではアクションであるとしましょう)であるマップ(グラフアブストラクトの)を指定して最短パスを見つけます。この場合、距離の代わりに、各アークには「値」があります)

これが本質的な構造です。

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
}

このデータ型を使用して、各パスの最終合計を確認することに基づいて、最適なソリューションを取得するために実行可能なすべてのオプションのマップを作成できます。したがって、パターンを探す秒数が長いほど、非常に最適なパスを見つける可能性が高くなります。

地図上の道路のすべてのセグメントには、その値を表す距離があり、道路のすべての停車地は1秒のマークです。これは、次に進む場所(実行するアクション)を決定する時間だからです。 。簡単にするために、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?
}
}
于 2013-03-21T21:57:48.897 に答える
1

編集:問題をもう少し読み直した後、重み付けされたスケジューリングアルゴリズムを調整して、問題のステートメントに合わせる必要があることがわかりました。この場合、選択したアクションのクラスに一致する重複するアクションと、同じ時点で開始するアクションのみをセットから取り出します。IE を選択した場合、セットから削除しa1たいのですが、削除したくありません。a2b1b2

これは、この pdfで詳しく説明されている加重スケジューリングの問題と非常によく似ています。基本的に、重みはアクションの値であり、間隔は (開始時間、開始時間 + クールダウン) です。動的計画法のソリューションはメモ化できるため、O(nlogn) 時間で実行できます。唯一の難しい部分は、事前に決められた解決策を利用できるようにする加重間隔問題のように問題を修正することです。

間隔には開始時刻と終了時刻が設定されていないため (つまり、特定のアクションをいつ開始するかを選択できます)、設定された時間範囲を想定して、指定されたすべてのアクションの可能なすべての開始時刻を列挙し、これらの静的開始/動的計画法ソリューションで終了時間。1 秒間だけアクションを開始できると仮定すると、アクション A を間隔 (0-2,1-3,2-4,...) で実行し、アクション B を (0-3,1-4,2 で実行) 実行できます。 -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... 
于 2013-03-21T21:05:42.927 に答える
0

常に最も多くのポイントに値する利用可能なアクションを選択してください。

于 2013-03-23T00:12:22.220 に答える