装载问题(0-1背包问题)

装载问题(0-1背包问题)

1、问题

在这里插入图片描述

2、解析

思路:轻者先装,直到再装任何集装箱将使轮船载重量超过C时停止。

  • 定理:对于任何正整数k,算法(轻者先装)对k个集装箱的实例得到最优解。
    证明:

  • 数学归纳法:K=1,只有一个集装箱,其重量小于C。任何装法都只有一种方式,因此都是最优解,所以轻者先装也是最优解。

  • 假设归纳:假设算法对于规模为K的输入都能得到最优解。
    考虑规模为k+1的输入,N={1,2,…,k+1},W={w1,w2,…,w(k+1)}是集装箱的重量,w1<=w2<=…<=w(k+1).

  • 从N中拿掉最轻的集装箱,得到k规模的输入:
    N’=N-{1}={2,3,…,K+1}
    W’=W-{w1}
    C’=C-w1
    根据归纳假设,对于k个输入,N’,W’,C’的最优解为I’,即I’为N’,不含I的最优解

    令I=I’∪{1}
    那么I必然是N的最优解,也是N,W,C的解

  • 反证法证明I必然是N的最优解:
    假设I不是N的最优解

  • 构建最优解1*(N,含1):假设I不是N的最优解。则必然存在最优解I*,如果I中没有1,用1替代I中的第一个集装箱标号得到的解也是最优解(个数不变,因此也是最优解),使得I为包含1的关于N的最优解且|I|>|I|

  • 构建最优解I*’(N’,不含1):因为I为包含1的关于N的最优解,==构建的I’=I*-{1}是不包含1的最优解(证明如下)==,即关于N’、W’、C’的最优解(N’、W’、C’不包含1)
    - 构建的I*’=I*-{1}是不包含1的最优解(待证明)
    反证法:如果I*‘=I*-(1}不是不包含1的最优解,那么存在最优解I*’’(N’,不含1),使得|I*’|<|I*’’|,
    即|I*’+{1}<|I*’’+{1}),与I*’+{1}=I为最优矛盾,因此I’=I*-{1}是不包含1的最优解。

  • 构建的最优解I*’与归纳假设的最优解I’比较:由|I*|>|I|得,|I*’|=|I*-{1}>|I-{1}|=|I’|,与I’的最优性矛盾(最优解I*-{1}大于最优解I’)。

3、设计

#include <iostream>
using namespace std;
const int n=100;
int t,weight1,weight2,weight[n];
int currentw,bestw,restw; 
int result[n],bestresult[n];
int i;
void Back(int &i)
{
    while(i>1&&result[i]==0)
    {
        --i;
    }
    if(result[i]==1)
    {
        result[i] = 0;
        currentw =currentw+ weight[i];
        i =i+1;
    }
}
void Loading(int weight[])
 {
    while(i<=t)
    {
        if(currentw-weight[i]>=0)
        {
            currentw =currentw- weight[i];
            result[i] = 1;
            i =i+1;
        }
        else
        {
            result[i] = 0;
            i =i+1;
        }
    }
    if(currentw<bestw)
    {
        bestw = currentw;
        for(i=1;i<=t;i++) 
		    bestresult[i]=result[i];
    }
    Back(i);
    if(i==1)
    {
        cout<<"第一艘轮船:"<<endl;
        for(i=1;i<=t;i++) 
		    if(bestresult[i]) 
			    cout<<i<<" ";
        cout << endl;
 		cout<<"第二艘轮船:"<<endl;
        for(i=1;i<=t;i++) 
		    if(0==bestresult[i]) 
			    cout<<i<<" ";
        return;
    }   
    else
        Loading(weight);
 }
 int main()
 {

    i = 1;
	cout << "请输入集装箱的个数:";
	cin >> t;
	cout << "请输入第1艘和第2艘轮船的载重:";
	cin >> weight1>>weight2;
	cout << "请依次输入货物的重量"<<endl;
    currentw = weight1;
    bestw = weight1;
    weight[0] = 0;
    for(i=1;i<=t;i++) 
    {
        cin>>weight[i];
        restw=restw+weight[i];
    }
    i = 1;
    Loading(weight);
    return 0;
 }
/*
7
152 130
90 80 40 30 20 12 10
*/  

4、分析

时间复杂度:O(nlogn)

5、源码

装载问题(0-1背包问题)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值