轮船装载问题

#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];//当前队首节点为扩展节点
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值