【千里码】老王装货 最优化问题

顺丰速运,全货机专机运输,提供高效的便捷服务,更快更安全!

首先,是快捷的时效服务。自有专机和400余条航线的强大航空资源以及庞大的地面运输网络,保障客户的快递在各环节最快发运。 

其次,是安全的运输服务。顺丰速运自营的运输网络,给消费者提供标准、高质、安全的服务。

由此,顺丰速运在消费者的心中留下了完美的形象,从而提高了企业的业绩,也奠定了其在整个快递领域中的基础。

顺丰快递每天能收到成千上万的物流单,每个物流单的重量不一。 现在顺丰快递的货车司机隔壁老王开着顺丰的标配货车(限载5吨,含5吨,不考虑限高),想要一次性拿走尽可能重的货物,这些货有红木沙发,有钢材等等。

以下是货物清单:

货物编号货物重量(单位:kg)
1509
2838
3924
4650
5604
6793
7564
8651
9697
10649
11747
12787
13701
14605
15644

请在答题框下输入你想装运的货物的编号,用“-”分隔。

比如1-2-3代表同时装入编号为1,2,3的货物,此时货物总重为509(1号货物)+838(2号货物)+924(3号货物)=2271kg,远小于限载额——5吨,隔壁老王会被吐槽的。。。

比如1-5-8-9-11-12-14代表同时装入编号为1,5,8,9,11,12,14的货物,此时货物总重为509(1号货物)+604(5号货物)+651(8号货物)+697(9号货物)747(11号货物)+787(12号货物)+605(14号货物)=4600kg,这时与限载额——5吨,就比较接近了,隔壁老王会很高兴。。。

很明显的背包DP问题。求出最大值比较简单,关键是怎么求路径。

这里用了两种方法,一种是递归一种是非递归的。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[18][5555],w[22];
void print(int i,int j)
{
    if(i==0)return;
    if(dp[i][j]==dp[i-1][j-w[i]]+w[i]){
        print(i-1,j-w[i]);
        printf("%d-",i);
    }else{
        print(i-1,j);
    }
}

int main()
{
    int i=0,j,t=0,n;

    scanf("%d",&n);
    for(j=1;j<=n;j++){
        scanf("%d %d",&i,&t);
        w[i]=t;
    }
    for(i=1;i<=n;i++){
        for(j=0;j<=5000;j++){
            if(j>=w[i]){
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+w[i]);
            }else{
                dp[i][j]=dp[i-1][j];
            }
        }
    }

    printf("%d\n",dp[15][5000]);
    print(15,5000);
    printf("\n");
   int tmp=5000;
   for(int i=n;i>=1;i--){//这个顺序很重要,不能从1到n,它的顺序应该和DP的顺序相反
        if(tmp>=w[i]&&dp[i][tmp]==dp[i-1][tmp-w[i]]+w[i]){
            printf("%d-",i);
            tmp-=w[i];
        }
   }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值