问题: 跨境电商在一个物流订单是有限制商品重量以及商品价值的,在一次性购买多个商品的时候,需要将商品拆分成多个订单,如何将挑选商品组合,才能使这个商品最合理?
实现思路:动态规划 背包问题
有i个商品(多个商品拆分为多个数量为1),每件商品的重量为w[i]价值为v[i]
最大重量j,i个商品的最大重量为f[i][j]
状态转移方程 f[i][j]=max(f[i-1][j-w[i]]+w[i],f[i-1][j])
主要是第i个商品是否加入的的问题
加入: 背包装的重量f[i][j] =背包减去当前重量后的最大容量(f[i-1][j-w[i]])+当前背包容量(w[i])
不加入: 背包装的重量f[i][j] = f[i-1][j]
判断最大的存放在f[i][j];
有背包容量10
重量 2,2,6,5,4
枚举j 从0->10 ,i 从1->5
如 f[5][10]=max(f[4][6]+w[5],f[4][10])
f[4][10] =max(f[3][5]+w[4],f[3][10])
f[4][6]=max(f[3][1]+w[4],f[3][6])
。。。。
直到获取前一个数是一个确定值
下面是PHP 的实现代码 ,获取在不超过最大价值的情况下的最大重量组合
$weight =50;
$val = 10;
$list=[
['w'=>2,'v'=>8],
['w'=>2,'v'=>4],
['w'=>6,'v'=>7],
['w'=>5,'v'=>12],
['w'=>4,'v'=>17],
];
//枚举所有最大值f[i][j]
$value=[];
//初始化 背包容量为0时候背包装的重量
for($i=0;$i<=count($list);$i++){
$value[$i][0]=['w'=>0,'v'=>0];
}
//初始化 商品为0时候背包容量装的重量
for($j=0;$j<=$weight;$j++){
$value[0][$j]=['w'=>0,'v'=>0];
}
for($i=1;$i<=count($list);$i++){
for($j=1;$j<=$weight;$j++){
$value[$i][$j]=$value[$i-1][$j];
if($j>=$list[$i-1]['w'] ){
$tempW = $value[$i-1][$j-$list[$i-1]['w']]['w']+$list[$i-1]['w'];
$tempV = $value[$i-1][$j-$list[$i-1]['w']]['v']+$list[$i-1]['v'];
}else{
$tempW = 0;
$tempV = 0;
}
//不超过最大价值,以及大于f[i-1][j]
if($list[$i-1]['w']<=$j && $tempW>$value[$i][$j]['w'] && $tempV<$val){
$value[$i][$j]=['w'=>$tempW,'v'=>$tempV];
}
}
}
$maxWeight= $value[count($list)][$weight]['w'];
//逆推选中的商品
$lastWeight=$maxWeight;
$res=[];
$i=count($list);
do{
if(($lastWeight-$list[$i-1]['w'])>=0 &&($value[$i-1][$lastWeight-$list[$i-1]['w']]['w']+$list[$i-1]['w'])==$lastWeight){
$lastWeight = $lastWeight-$list[$i-1]['w'];
$res[]=$i-1;
}
$i--;
}while($i>0);
递归处理$list商品直到里面的所有商品处理完