ローディングの問題:あるN担体上にロードされる2つの容器C1、C2の重量であり、船舶コンテナの重量はIをWiである、とΣwi<= C1 + C2。
これらの2隻の船にこれらのn個のコンテナを積み込むための合理的な積み込み計画があるかどうか尋ねます。もしそうなら、積載計画を見つけてください。
問題分析:実際には、すべての商品を最初の船に積み込み、次に2番目の船に積み込んで解決策を与えることができるかどうかとして理解できます。
考慮すべき主なことは、最初の船をどのようにインストールするかです?この問題が解決されたら、残りを2隻目の船に入れることができます。
前に、読み込みの問題について説明しましたが、ポータル:読み込みの問題|バックトラッキング:01選択(最大プルーニング)です。負荷問題と最適負荷問題の比較について説明しますが、この質問では貪欲アルゴリズムは使用できません。ここでは繰り返しません。実際、上記から、バックトラッキングはすべてのスキームでdfsを実行し、途中で最適化を剪定することであることがわかります。ここでのブランチとバインドされたルールは、すべてのソリューションでbfsを実行し、常に最適なポイントから毎回検索することです。
1.選択ツリーのブランチとバインドされたアルゴリズム
バックトラッキングアルゴリズムの列挙(選択ツリー)の本質を理解した後、ブランチ境界を使用するのは簡単です。詳細はここでは説明しません。バックトラックのdfをbfsに変更するだけです。詳細については、読み込みの問題|バックトラック:01選択(最大の剪定)を参照してください。
以下は、決定木のモデルです。このモデルでは、説明するノードを、キービットを使用して優先度キューに格納する必要があります。最大のキーを持つノードは、議論を続けるために毎回削除されます。
ここで最も重要なことは、各ノードの理解に注意を払うことです。
- ノードは、特定の場所で実行される意思決定計画の結果である必要があります
- ノードには、cur_w(船の現在の重量)、r(選択されていない残りの項目の総重量)、キーワードキー(cur_w + r)、およびstep(項目番号を取得するために次の項目を選択する必要があります)が必要です。
- ノードが取り出されると、ノードによって保存されたデータ状態でディスカッションが続行されます。ステップアイテムを配置するかどうかには、2つの選択肢があります。優先キューに適切な決定子ノードを追加し続けます
注意:
- アイテムの各重みは、0から始まる配列wに格納されます。したがって、ノードでstep = nの場合、ノードはリーフノードであり、決定が完了したことを意味します。
- キーワードキーは、実際には、このノードが存在する決定ラインの最終回答の上限です。
このブランチとバインドされたメソッドは最適化およびプルーニングされ、制約条件、バインドされた条件が追加されました。したがって、上の図の決定ポイントの一部は省略されています!
2.コードの実装
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct node {
int key; //key = cur_w + r,关键字:上界
int cur_w; //当前船上的重量
int r; //未选择货物的剩余总重
int step = 0; //当前搜索的层数(在讨论哪个物品)
/* 构造函数 */
node(int k, int cw, int r, int s) {
key = k;
cur_w = cw;
this->r = r;
step = s;
}
/* 重载 struct node 的比较运算符
* 方便后面建立优先队列的大小定位 */
friend bool operator<(struct node x, struct node y) {
return x.key < y.key;
}
} Node;
int best_w = 0;
int w[100]; //待选物品的重量
int n; //题中待选物品的数量
int c; //船的最大载重
int cur_w = 0; //当前船上的重量
int r; //当前待选物品的总重量
int step; //当前层数
void bfs() {
priority_queue<Node> Q; //定义一个优先队列
Node head(r, 0, r, 0); //从根节点开始遍历
/* 当遍历到叶节点(每一件货物都讨论了)就结束 */
while (head.step <= n) {
step = head.step;
cur_w = head.cur_w;
r = head.r - w[step]; //对于剩余货物总重来说,加不加都要减去当前货物
int maybe = cur_w + w[step]; //如果加上当前货物,船上将有重量
/* 选择当前物品 (满足约束条件)*/
if (maybe <= c) {
best_w = max(best_w, maybe); //更新最优值
Node temp(maybe + r, maybe, r, step + 1);
Q.push(temp);
}
/* 不选择当前物品 (满足限界条件)*/
if (head.key > best_w) {
Node temp(cur_w + r, cur_w, r, step + 1);
Q.push(temp);
}
/* 出队key最大的 */
head = Q.top();
Q.pop();
}
}
int main() {
w[0] = 16;
w[1] = 15;
w[2] = 15;
r = 16 + 15 + 15;
c = 30;
n = 3;
bfs();
cout << best_w << endl;
}