綱引きアルゴリズム
この問題では、整数のセットが与えられます。2つのサブセットの合計の差ができるだけ小さくなるように、整数を2つの部分に分割する必要があります。したがって、私たちの目標は、ほぼ等しい強さの2つのグループを分割して、綱引きゲームに参加することです。
サブセットnのサイズが偶数の場合はn/2に分割する必要がありますが、nの値が奇数の場合、1つのサブセットのサイズは(n-1)/ 2であり、別のサブセットのサイズは( n + 1)/2。
入力と出力
Input: A set of different weights. {23, 45, -34, 12, 0, 98, -99, 4, 189, -1, 4} Output: The left and right subset to distribute the weights to make the difference minimum. Left: {45, -34, 12, 98, -1} Right: {23, 0, -99, 4, 189, 4}
アルゴリズム
tugOfWar(weight, n, curr, select, sol, diff, sum, total, pos)
入力- 与えられた重みのセット、重みの数、現在のリスト、選択されたアイテムの数、2つのサブセットの合計の差、すべてのアイテムの合計、サブセット内の合計、選択された要素の位置。
出力- 左右のサブセット用に選択されたソリューションセット。
Begin if pos = n, then //when all elements are taken return if (n/2-select) > (n - pos), then return tugOfWar(weight, n, curr, select, sol, diff, sum, total, pos+1) select := select + 1 total := total + weight[pos] curr[pos] := true //when item at pos is taken if select = n/2, then if difference of (sum/2 and total) < diff, then diff := difference of (sum/2 and total) for i := 0 to n, do sol[i] := curr[i] done else tugOfWar(weight, n, curr, select, sol, diff, sum, total, pos+1) curr[pos] := false //remove current element if not properly done End
例
#include <iostream> #include<cmath> using namespace std; void tugOfWar(int* weight, int n, bool curr[], int select, bool sol[], int &diff, int sum, int total, int pos) { if (pos == n) //when the pos is covered all weights return; if ((n/2 - select) > (n - pos)) //left elements must be bigger than required result return; tugOfWar(weight, n, curr, select, sol, diff, sum, total, pos+1); select++; total += weight[pos]; curr[pos] = true; //add current element to the solution if (select == n/2) { //when solution is formed if (abs(sum/2 - total) < diff) { //check whether it is better solution or not diff = abs(sum/2 - total); for (int i = 0; i<n; i++) sol[i] = curr[i]; } } else { tugOfWar(weight, n, curr, select, sol, diff, sum, total, pos+1); } curr[pos] = false; //when not properly done, remove current element } void findSolution(int *arr, int n) { bool* curr = new bool[n]; bool* soln = new bool[n]; int diff = INT_MAX; //set minimum difference to infinity initially int sum = 0; for (int i=0; i<n; i++) { sum += arr[i]; //find the sum of all elements curr[i] = soln[i] = false; //make all elements as false } tugOfWar(arr, n, curr, 0, soln, diff, sum, 0, 0); cout << "Left: "; for (int i=0; i<n; i++) if (soln[i] == true) cout << arr[i] << " "; cout << endl << "Right: "; for (int i=0; i<n; i++) if (soln[i] == false) cout << arr[i] << " "; } int main() { int weight[] = {23, 45, -34, 12, 0, 98, -99, 4, 189, -1, 4}; int n = 11; findSolution(weight, n); }
出力
Left: 45 -34 12 98 -1 Right: 23 0 -99 4 189 4
-
フォードファルカーソンアルゴリズム
Ford-Fulkersonアルゴリズムは、特定のグラフの開始頂点からシンク頂点への最大フローを検出するために使用されます。このグラフでは、すべてのエッジに容量があります。 SourceとSinkという名前の2つの頂点が提供されます。ソース頂点にはすべて外向きのエッジがあり、内向きのエッジはありません。シンクにはすべて内向きのエッジがあり、外向きのエッジはありません。 いくつかの制約があります: エッジのフローは、そのグラフの所定の容量を超えません。 流入フローと流出フローも、ソースとシンクを除くすべてのエッジで等しくなります。 入力と出力 入力:隣接行列:0 10 0 10 0
-
フロイドウォーシャルアルゴリズム
Floyd-Warshallアルゴリズムを使用して、特定の重み付きグラフからすべてのペアの最短経路問題を見つけます。このアルゴリズムの結果として、グラフ内の任意のノードから他のすべてのノードまでの最小距離を表す行列が生成されます。 最初、出力行列はグラフの指定されたコスト行列と同じです。その後、出力行列はすべての頂点kを中間頂点として更新されます。 このアルゴリズムの時間計算量はO(V ^ 3)です。ここで、Vはグラフ内の頂点の数です。 入力と出力 Input: The cost matrix of the graph. 0 3 6 ∞ ∞ ∞ &