动态规划算法实验报告

  • 格式:doc
  • 大小:232.08 KB
  • 文档页数:7

1 南京信息工程大学 滨江学院 实验(实习)报告

1. 实验目的

动态规划通常用来求解最优化问题。通过本次实验掌握动态规划算法。通过矩阵连乘问题和0-1背包问题实现动态规划算法。学会刻画问题的最优结构特征,并利用最优化问题具有的重叠子问题性质,对每个子问题求解一次,将解存入表中,当再次需要这个子问题时直接查表,每次查表的代价为常量时间。

2. 实验内容及分析设计过程

1. 矩阵链乘法问题

矩阵链乘法问题可描述如下:给定个矩阵的链,矩阵的规模为,求完全括号方案,使得计算乘积所需的标量乘法次数最少。

令m[i,j]表示计算矩阵所需标量乘法次数的最小值,那么,原问题的最优解计是m[1,n]。

最小代价括号化方案的递归求解公式为

采用自底向上表格法代替上述递归算法来计算最优代价。

为了实现自底向上方法,我们必须确定计算m[i,j]时需要访问哪些其他表项。上述公式显示,

j-i+l 个矩阵链相乘的最优计算代价m[i,j] 只依赖于那些少于j-i+l 个矩阵链相乘的最优计算代价。因此,算法应该按长度递增的顺序求解矩阵链括号化问题,并按对应的顺序填写表m。

对如下输入

A1 A2 A3 A4 A5 A6

3035 3515 155 510 1020 2025

程序运行结果为

2. 背包问题

2 给定n个重量为价值为的物品和一个承重为W的背包。求这些物品中最有价值的一个子集,并且要能装到背包中。

设V[i,j]是能够放进承重量为j的背包的前i个物品中最有价值子集的总价值。则递推关系为

初始条件V[0,j]=0(j>=0),V[i,0]=0(i>=0)

我们的目标是求V[n,W]。递归式给出了V[i,j]的计算顺序,V[i,j]只依赖与前一行的那些项。故可以逐行计算V[i,j].

对于物品数量n=5,w[n]={2,2,6,5,4},v[n]={6,3,5,4,6},背包总重量c=10

程序运行结果为

3. 实验小结

通过本次实验加深了我对动态规划算法的理解。而且对动态规范编写代码解决一个实际问题有了进一步的认识。即当算法考虑的原问题的每一个子问题,算法都需要计算一个最优解。换句话说,所有算法生成的表项表示算法考虑的子问题的最优解。这时候用动态规范把每一个最优解求出来(利用递归公式),就能够保证最后求得的一定是最优解。

附录

1. 矩阵链乘问题

MatrixChainTest.java

public class MatrixChainTest

{

public static void main(String [] args)

{

int p[]={30,35,15,5,10,20,25};

MatrixChain mc=new MatrixChain(p);

mc.solve();

}

}

class MatrixChain

3 {

private int m[][];

private int s[][];

public int p[];

public MatrixChain(int [] p0)

{

p=p0;

}

public void solve()

{

m=new int[p.length][p.length];

s=new int[p.length-1][p.length];

MatrixChainOrder();

System.out.printf("最少乘次数:%d\n",m[1][p.length-1]);

PrintOptimalParens(1, p.length-1);

System.out.println();

}

private void MatrixChainOrder()

{

int n=p.length-1;

for(int i=1;i<=n;i++)

{

m[i][i]=0;

}

for(int l=2;l<=n;l++)

{

for(int i=1;i<=n-l+1;i++)

{

int j=i+l-1;

m[i][j]=Integer.MAX_VALUE;

for(int k=i;k<=j-1;k++)

{

int q=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];

if(q

{

m[i][j]=q;

s[i][j]=k;

}

}

}

}

}

4 private void PrintOptimalParens(int i,int j)

{

if(i==j)

{

System.out.print("A"+i);

}

else

{

System.out.print("(");

PrintOptimalParens(i,s[i][j]);

PrintOptimalParens(s[i][j]+1,j);

System.out.print(")");

}

}

}

2. 背包问题

KnapsackTest.java

public class KnapsackTest

{

public static void main(String [] args)

{

int w[]={2,2,6,5,4};

int v[]={6,3,5,4,6};

int W0=10;

Knapsack ks=new Knapsack(w, v, W0);

ks.solve();

}

}

class Knapsack

{

int w[];//重量

int v[];//价值

int V[][];//V[i][j]表示物品0,1,...i放入限重j的背包所能获取的最大价值

int c[];//c[i]=0表示选择物品i,c[i]=0表示不选物品i

int W;//限重

public Knapsack(int w0[],int v0[],int W0)

{

w=w0;

v=v0;

5 W=W0;

}

private void MaximizeValue()

{

V=new int[w.length][W+1];

for(int j=0;j<=W;j++)

{

if(j>=w[0])

{

V[0][j]=v[0];

}

else

{

V[0][j]=0;

}

}

for(int i=0;i

{

V[i][0]=0;

}

for(int i=1;i

{

for(int j=1;j<=W;j++)

{

if(j>=w[i]&&((V[i-1][j-w[i]]+v[i])>V[i-1][j]))

{

V[i][j]=V[i-1][j-w[i]]+v[i];

}

else

{

V[i][j]=V[i-1][j];

}

}

}

}

private void Choose(int i,int j)

{

if(i==0)

{

if(j>=w[0])

c[0]=1;

else

c[0]=0;

6 return ;

}

if(V[i][j]!=V[i-1][j])

{

c[i]=1;

Choose(i-1,j-w[i]);

}

else

{

c[i]=0;

Choose(i-1,j);

}

}

public void solve()

{

MaximizeValue();

// for(int i=0;i

// {

// for(int j=0;j<=W;j++)

// {

// System.out.printf("%d ",V[i][j]);

// }

// System.out.printf("\n");

// }

System.out.printf("最大价值:%d\n",V[w.length-1][W]);

c=new int[w.length];

Choose(w.length-1,W);

System.out.printf("选择的物品:");

for(int i=0;i