背包算法递归实现,递归转动态规划的一般方法java实现

来源:互联网 发布:java中实现多线程方法 编辑:程序博客网 时间:2024/06/05 18:56

背包算法一般采用贪心算法求近似解,但是在做作业的时候常常遇到只要求实现,所以给定特地度量为1的背包算法

这样的情况常常采用的是动态规划实现

动态规划的关键是求解的过程中子问题的解是不独立的,可以这样理解,即他们的解是相关联的,求f(n)的 时候必然

会用到f(n-1)的解,以此类推。所以,才用一组内存存放前N-1项的解是必然的。

一般情况处理一个问题的首先想到代码实现是递归,其次动态规划。下面采用一般方法将递归代码转为动态规划。

举个简单例子:

斐波那契数列实现

        static final int maxn=20000;
static long knownf[]=new long[maxn];

      static long func(int i)   //递归实现

          {

              if(i==0||i==1) 

                    return 1;

              else 

                    return func(i-1)+func(i-2);

          }

递归的代码非常简单,但是这样求解F(N)是不合理的,重复计算子问题,极易使栈溢出

下面是动态规划实现
static long f(int i)
{

if(i==0||i==1) return knownf[i]=1;

else
{
long t=0;
if(knownf[i-1]!=0) return knownf[i]=knownf[i-1]+knownf[i-2];
else 
{
t=f(i-1)+f(i-2);
System.out.println("f("+i+")="+"f("+(i-1)+")+"+"f("+(i-2)+")");
return knownf[i]=t;
}
}
}

容易发现这个算法用一个数组存储了F[1]-F[N]的一组解,函数结构仍是自顶向下,但是求解过程是线性的

首先查看F[i-1](即第i-1的解)是否已求,将其结果输出;否则,递归求解f(i-1)+f(i-2);形式和递归一样

只是求解后返回一个解填写数组

同样,下面是背包算法的求解:

class item
{
public int size;
public int value;
public item(int size,int value)
{
this.size=size;
this.value=value;
}
}
public class Test5_12 {

static item[] items=new item[5];
public static void init()
{
items[0]=new item(1,2);
items[1]=new item(2,2);
items[2]=new item(4,3);
items[3]=new item(3,5);
items[4]=new item(6,9);
}
//递归出口space<0
public static int knap(int cap)
{  // cap is bag size
int i,space,max,t;
for( i=0,max=0;i<5;i++)
if((space=cap-items[i].size)>=0)//向下搜索返回cap=space最大解 
               if((t=knap(space)+items[i].value)>max)//搜索到叶节点时候返回max
               max=t;              
   return max;

}

public static void main(String[] args) {

// TODO Auto-generated method stub
        init();
        System.out.println(knap(6));
}

}

上面是递归求解knap,值得注意的是函数public static int knap(int cap);改为

public static int knap(int cap,int  k) k作为未访问的物品序列,此时即为0-1背包算法

下面改为动态规划实现:

static int knap(int M)

{

      int i,space,max,maxi=0,t;

      if(maxKnown[M]!=unknow) 

           return maxKnown[M];

      for(i=0,max=0;i<N;i++)

            if((space=M-items[i].size)>=0)

                  if((t=knap(space)+items[i].val)>max)

                      {

                           max=t;

                           maxi=i;

                     }

   maxKnown[M]=max;itemKnown[M]=items[maxi];

       return max;

}

上面形式和递归实现很像,与上一个例子不同的是,背包问题填的是一张二维数组,斐波那契数列填的是一个一维数组





原创粉丝点击