您的位置:首页 > 其它

动态规划之——背包问题

2017-11-11 22:20 253 查看
0,1背包和完全背包。本文只讨论完全背包。

   1,什么是动态规划?

多阶段问题是整个决策问题分为多个阶段,不同阶段之间相互关联。动态规划是针对最优化问题的一种途径和方法。

通过组合子问题的解来求解原问题。将子子问题的解求出来,放在表格之中。等到求子问题的解时,从表格中取出子子问题的解,通过递推关系,找出子问题的解,又放在表格中,最后又通过递推关系,找到原问题的解。个人看法,多阶段问题由于决策的不同会有不同的情况,那么如何找出最优的情况呢。穷举出所有情况不就行了吗?当然我们可以通过肉眼,不断的寻找所有情况,但用代码要如何写出来?动态规划就是说明的这一方法。

    2,递推关系

          f(i,j)=max y*p[i]+f(i+1,j-c[i])  (0<=y<=j/c[i])    

i代表第i个物品,j代表第i个阶段初的背包容量

f(i,j)表示第i种物品选到最后一种物品,总容量小于或等于j的最优包装方案的价值总获得。

y表示第i种物品放入的数量,p[i]是第i种物品的价值,c[i]是第i个物品的容量。

在设计时将这个f(i,j)的函数抽象成了一个二维数组(就是个表),f[i][j]表示函数f(i,j)的值。注意多阶段问题的最后一个阶段也就是表的最后一行的数是如何初始化的,现在来看代码。

      3,具体问题

       一个包capacity为10,要求将容量分别为2,3,4,7的物品放入包中,每个物品可以放多次,也可以不放,物品

的价值分别为1,3,5,9。要求放完所有物品放玩之后,包中的物品总价值最大。

物品  1     2     3     4

容量  2     3     4     7

价值  1     3     5     9

分析,f(1,10)表示从第1个物品,到最后一个物品(第4个物品)在容量为10的条件下选择的总价值最大的方案对应的价值数。它等于max{f(2,10),1*1+f(2,10-1*2),1*2+f(2,10-2*2),......,1*5+f(2,10-2*5)}。第1个物品在容量为10的前提下,最多可以放5个,最少可以一次都不放,对应6个决策,从6个决策中选出价值最大的决策。

   

输出结果为:[0,1,0,1]
     12
表示第1和第3个物品不放,第2和第4个物品放。

public class DynamicPlanning {
public static void main(String[] args) {
int[] c={0,2,3,4,7};
int[] p={0,1,3,5,9};

System.out.println(maxProfit(10, 4, c, p));
}

//capacity包的初始容量,N为物品个数,c[k]为物品k容量 p[k]为物品k的价值
//f[i][j]为从i到N的物品选择总重量不超过j的总价值最高的值。
public static int maxProfit(int capacity,int N,int[] c,int[] p){
int[] numsOfProduct=new int
;//记录每个物品具体放多少的数组
int[][] f=new int[N+1][capacity+1];
for(int j=0;j<=capacity;j++)
{//初始化最后一个阶段,你虽然不知道容量具体是多少,但容量范围就是(0,capacity)之间的整数。
int y=j/c
;//第N个物品在j容量下的最大数量
if(y>=1)    f
[j]=p
*y;//数量最大,价值最大
else  f
[j]=0;
}

for(int i=N-1;i>=1;i--)
{
for(int j=0;j<=capacity;j++)
{
int y=j/c[i];//第N个物品在j容量下的最大数量
if(y==0) f[i][j]=f[i+1][j];//第i个物品的容量大于剩余容量j,不放这个物品
else
{
int[] results=new int[y+1];
for(int m=0;m<=y;m++)
results[m]=m*p[i]+f[i+1][j-m*c[i]];//把i物品放入的数量不同的结果存入数组,再从中取出最大值

Arrays.sort(results);
int max=results[y];
f[i][j]=max;
}
}
}
//你会发现其实表中某些值根本用不到。
//计算最优决策的各个物品的数量情况。
int j=capacity;int max_f=f[1][capacity];
for(int i=1;i<=N-1;i++)
{
int y=j/c[i];//在j容量下能够存储的最大数量

for(int m=0;m<=y;m++)
{

if(m*p[i]+f[i+1][j-m*c[i]]==max_f)
{
numsOfProduct[i-1]=m;
j=j-c[i]*m;
max_f=f[i+1][j];break;
}

}
}
numsOfProduct[N-1]=j/c
;
System.out.println(Arrays.toString(numsOfProduct));
return f[1][capacity];
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息