问题描述
有一批共n个集装箱要装上2艘载重量分别为和的轮船,其中集装箱i的重量为,且;要求确定是否有一个合理的装载方案可将这个集装箱装上这2艘轮船。如果有,找出一种装载方案。
即
输入:船的载重C1,集装箱个数n以及各个集装箱的重量W=<w1,w2,…,wn>
输出:一种装载方案,即:第一艘船上装入哪些集装箱
为了提高内存利用率,下面代码将从数组0位开始,最后输出结果进行+1操作
注意:此文章所示代码不考虑剪枝 (优化) 操作
递归回溯
代码
#include <iostream>
using namespace std;
// 工作流类
class Work
{
public:
// 载重
int c = 0;
// 现重
int c_now = 0;
// 最有重量
int bestW = 0;
// 集装箱数量
int n = 0;
// 集装箱重量
const int *w = NULL;
// 最优装载方案
bool *bestWays = NULL;
// 目前选择情况
bool *nowWays = NULL;
// 构造
Work(const int *_w, const int _n, const int _c)
{
// 接收传入的参数
w = _w;
n = _n;
c = _c;
// 初始化
bestWays = new bool[n]{false};
nowWays = new bool[n]{false};
// 计算最优解
loading(0);
}
// 析构
~Work()
{
delete[] bestWays;
delete[] nowWays;
}
// 构造最优解-递归实现
void loading(int i)
{
// 检查是否到达末尾
if (i >= n)
{
// 检查当前方案是否为最优方案
if (c_now > bestW)
{
// 当前为最佳方案
bestW = c_now;
memcpy(bestWays, nowWays, sizeof(bool) * n);
}
return;
}
// 判断当前集装箱能否被装载
if (c_now + w[i] <= c)
{
// 当前集装箱能被装载,进入情况
c_now += w[i];
nowWays[i] = true;
loading(i + 1);
// 撤销装载
c_now -= w[i];
nowWays[i] = false;
}
// 判断不包含此物品的情况
loading(i + 1);
}
};
int main()
{
// 所需变量
int c1, c2, *w, n, sum = 0;
// 输入
cout << "c1: ";
cin >> c1;
cout << "c2: ";
cin >> c2;
cout << "n: ";
cin >> n;
w = new int[n]{0};
cout << "w: ";
for (int i = 0; i < n; i++)
{
cin >> w[i];
sum += w[i];
}
// 计算最优解
Work work(w, n, c1);
// 输出结果
// 判断剩余集装箱能都被第二艘船装载
if (sum - work.bestW <= c2)
{
// 能被装载
cout << "can load,\nship1: ";
for (int i = 0; i < n; i++)
if (work.bestWays[i] == true)
cout << i + 1 << " ";
cout << "\nship2: ";
for (int i = 0; i < n; i++)
if (work.bestWays[i] == false)
cout << i + 1 << " ";
}
else
{
//不能被装载
cout << "cannot load";
}
return 0;
}
运行结果
c1: 152
c2: 130
n: 7
w: 90 80 40 30 20 12 10
can load,
ship1: 1 3 6 7
ship2: 2 4 5
迭代回溯
代码
#include <iostream>
using namespace std;
// 工作流类
class Work
{
public:
// 载重
int c = 0;
// 现重
int c_now = 0;
// 最有重量
int bestW = 0;
// 集装箱数量
int n = 0;
// 集装箱重量
const int *w = NULL;
// 最优装载方案
bool *bestWays = NULL;
// 目前选择情况
bool *nowWays = NULL;
// 构造
Work(const int *_w, const int _n, const int _c)
{
// 接收传入的参数
w = _w;
n = _n;
c = _c;
// 初始化
bestWays = new bool[n]{false};
nowWays = new bool[n]{false};
// 计算最优解
loading();
}
// 析构
~Work()
{
delete[] bestWays;
delete[] nowWays;
}
// 构造最优解-迭代实现
void loading()
{
// 当前层级
int i = 0;
// 循环退出标记
bool run = true;
// 状态(路径)记录
int *x = new int[n]{0};
while (run)
{
// 检查是否到达末尾
if (i >= n)
{
// 检查当前方案是否为最优方案
if (c_now > bestW)
{
// 当前为最佳方案
bestW = c_now;
memcpy(bestWays, nowWays, sizeof(bool) * n);
}
i--;
continue;
}
//判断当前状态
switch (x[i])
{
case 0:
// 初状态
// 判断当前集装箱能否被装载
if (c_now + w[i] <= c)
{
// 当前集装箱能被装载,进入情况
c_now += w[i];
nowWays[i] = true;
x[i] = 1;
i++;
x[i] = 0;
break;
}
x[i] = 2;
break;
case 1:
// 遍历完左子树状态
// 撤销装载
c_now -= w[i];
nowWays[i] = false;
x[i] = 2;
break;
case 2:
// 未遍历左子树的状态
x[i] = 3;
i++;
x[i] = 0;
break;
case 3:
// 末状态
if (i == 0)
return;
i--;
break;
default:
return;
}
}
}
};
int main()
{
// 所需变量
int c1, c2, *w, n, sum = 0;
// 输入
cout << "c1: ";
cin >> c1;
cout << "c2: ";
cin >> c2;
cout << "n: ";
cin >> n;
w = new int[n]{0};
cout << "w: ";
for (int i = 0; i < n; i++)
{
cin >> w[i];
sum += w[i];
}
// 计算最优解
Work work(w, n, c1);
// 输出结果
// 判断剩余集装箱能都被第二艘船装载
if (sum - work.bestW <= c2)
{
// 能被装载
cout << "can load,\nship1: ";
for (int i = 0; i < n; i++)
if (work.bestWays[i] == true)
cout << i + 1 << " ";
cout << "\nship2: ";
for (int i = 0; i < n; i++)
if (work.bestWays[i] == false)
cout << i + 1 << " ";
}
else
{
// 不能被装载
cout << "cannot load";
}
return 0;
}
运行结果
c1: 152
c2: 130
n: 7
w: 90 80 40 30 20 12 10
can load,
ship1: 1 3 6 7
ship2: 2 4 5