问题描述
:有一批集装箱要装上一艘载重量为W的轮船,其中编号为i(0<= i<=n-1)的集装箱的重量为wi。现要从n个集装箱中选出若干个装上轮船,使得他们的重量之和恰好为W。如果找到任何一种解,返回true,否则返回false。
思路
:其实这道题运用了回溯法一个非常明显的特点,就是剪枝法。也就是狭义回溯法定义“回溯法=DFS+剪枝法”;另一种广义定义就是递归喽。
#include<iostream>
using namespace std;
int w[] = { 0,5,2,6,4,3 };
int x[100]; //这个x[]是用来判断是否选择装载,存放最优解向量的
int n = 5,W=10;
int maxw = 0;
void dfs(int i, int tw, int rw, int op[]) //求解简单装载问题
{ //tw表示选择的集装箱重量和,rw代表剩下集装箱重量和,op表示一种装载方案
if (i > n) //这个代表它把所有的集装箱都判断了是否装载,是走出递归的条件
{
if (tw > maxw)
{
maxw = tw;
for (int j = 1;j <= n;j++)
{
x[j] = op[j]; //这个x[]是用来判断是否选择装载,存放最优解向量的
}
}
}
else
{
if (tw + w[i] <= W) //左孩子结点剪枝
{
op[i] = 1; //选取第i个集装箱
dfs(i + 1, tw + w[i], rw - w[i], op);
}
if (tw + rw - w[i] > maxw) //虽然这步我有点小蒙,但是确实是如此
{
op[i] = 0;
dfs(i + 1, tw, rw - w[i], op);
}
}
}
void displaySolution(int n)
{
for (int i = 1;i <= n;i++)
{
if (x[i] == 1) {
printf("选择第%d个集装箱\n", i);
}
} //当然不仅把要求写了,顺便还把选择哪几个集装箱输出了
if (maxw == W)
cout << "ture";
else
cout << "false";
}
int main()
{
int tw = 0, rw = 20;
int op[100];
dfs(1, tw, rw, op);
displaySolution(n);
return 0;
}
自己懒得画这个解空间树,找了个课本的,(0,20)0代表tw,20代表rw