#include <stdio.h>
#include <stdlib.h>
const int N=10;//集装箱数量
int w[N];//N个集装箱重量
int c=5*N;//轮船最大承重量
int main()
{
int i;
printf("轮船最大载重为%d吨\n",c);
for(i=0;i<N;i++)
{
w[i]=rand()%N+1;//集装箱随机赋重量
printf("集装箱%d重%d吨\n",i,w[i]);
}
int count=0;//记录搜索到解的数量
int Q[10000];//使用数组用来模拟队列,空间换时间
int head=0;//队首指针
int tail=0;//队尾指针
Q[tail++]=0;//根节点入队
Q[tail++]=-1;//添加第0层节点的尾部标志,用来区分每一层的节点
i=0;//当前处于第0层
int Ew=Q[head];//当前扩展节点(根节点)对应的载重量
int bestw=0;//当前最优载重量
//下方代码用来记录未决策集装箱的总重量
int r=0;//剩余集装箱的重量,用于限界
//何时更新r值?
for(int j=1;j<N;j++)
{
r=r+w[j];//从第二个箱子开始所有集装箱的重量
}
while(N>0)//无限循环,直到循环内满足跳出条件
{
if(Ew+r>=bestw)//检查左孩子(左孩子为下一个集装箱不装,此时应当检查限界,请填写限界条件)
{
if(i==N-1)//如果左孩子已经到达叶节点
{
printf("搜索到一个解%d\n",Ew);//输出该解
count++;
if(Ew>bestw)//如果该解比最优值大
{
bestw=Ew;//更新最优值
printf("这个解比之前的解更优\n");
}
}
else//否则将左孩子入队
{
Q[tail++]=Ew;
}
}
else
{
printf("发生剪枝,剪枝类型是限界\n");
printf("发生在树的第%d层\n",i);
}
if(Ew+w[i]<=c)//检查右孩子(右孩子为下一个集装箱装船,此时应当检查约束)
{
if(Ew+w[i]>=bestw)
bestw=Ew+w[i];
if(i==N-1)//如果右孩子已经到达叶节点
{
printf("搜索到一个解:%d\n",Ew+w[i]);//输出该解
count++;
if(Ew+w[i]>bestw)//如果该解比最优值大
{
bestw=Ew+w[i];//更新最优值
printf("这个解比之前的解更优\n");
}
}
else//否则将右孩子入队
{
Q[tail++]=Ew+w[i];
}
}
else
{
printf("发生剪枝,剪枝类型是约束\n");
printf("发生在树的第%d层\n",i);
}
head++;//当前扩展节点生成了左右孩子,该节点出队并宣告死亡
if(Q[head]==-1)//如果队首是某一层的尾部标识,进入下一层
{
head++;//尾部标记出队
if(head==tail)//检查队列是否为空
{
printf("算法结束,共检查了%d个解\n",count);
printf("得到的最优解为:%d\n",bestw);
break;//退出循环
}
Q[tail++]=-1;//进入下一层前,插入尾部标识
i++;//进入下一层
Ew=Q[head];//当前队首节点为扩展节点
r=r-w[i];//更新未决策集装箱的总重量
}
else//否则
{
Ew=Q[head];//当前队首节点为扩展节点
}
}
}