实验三 动态规划

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验三动态规划
(一)、实验目的
通过编程实现动态规划的有关算法,理解动态规划的原理,掌握动态规划基本思想与应用技巧。

(二)、实验题目与要求:
实验题目1:最长公共子序列问题的算法
若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk}是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。

例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。

给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X 和Y的公共子序列。

给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。

实验要求:
1.理解动态规划算法的原理,认真阅读题目。

完善程序,实现该算法;
2.输入:X序列为xyxzyxyzzy, Y序列为xzyzxyzxyzxy
输出:二维数组c、最长公共子序列。

实验提示:
1)先求最长公共子序列,X和Y的最长公共子序列的长度记录于c[m][n]中
public static int lcsLength(char [ ]x,char [ ]y,int [ ][ ]b)
{ int m=x.length-1;
int n=y.length-1;
int [][]c=new int [m+1][n+1];
for (int i = 1; i <= m; i++) c[i][0]=0;
for (int i = 1; i <= n; i++) c[0][i]=0;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++) {
if (x[i]= =y[j]) { c[i][j]=c[i-1][j-1]+1; b[i][j]=1;}
else if (c[i-1][j]>=c[i][j-1]) { c[i][j]=c[i-1][j]; b[i][j]=2;}
else { c[i][j]=c[i][j-1]; b[i][j]=3;}
}
return c[m][n];
}
2)然后构造最长公共子序列
public static void lcs(int i,int j,char [] x,int [][] b)
{ if (i = =0 || j= =0) return;
if (b[i][j]= = 1){
lcs(i-1,j-1,x,b);
System.out.print(x[i]);
}
else if (b[i][j]= = 2) lcs(i-1,j,x,b); else lcs(i,j-1,x,b);
}
[][][]{}⎪⎩⎪⎨⎧<+++==-<≤j i p p p j k m k i m j i j i m j k i j
k i 1,1,min 0,实验题目2:用两台处理机A 和B 处理n 个作业。

设第i 个作业交给机器A 处理时需要时间ai ,若由机器B 来处理,有ai ≥bi ,而对于某些j ,j ≠i ,有aj<bj 。

既不能将一个作业分开由两台机器处理,也没有一台机器能同时处理2个作业。

设计一个动态规划算法,使得这两台机器处理完成这n 个作业的时间最短(从任何一台机器开工到最后一台机器停工的总时间)。

实验要求:
1. 理解动态规划算法的原理,认真阅读题目。

完善程序,实现该算法;
2. 研究一个实例:
(a1, a2, a3, a4, a5, a6) = (2, 5, 7, 10, 5, 2) ;
(b1, b2, b3, b4, b5, b6)=(3, 8, 4, 11, 3, 4)。

结果显示处理完所有作业的最短时间。

实验题目3:计算矩阵连乘积
给定n 个矩阵{A 1,A2 ,...,An },其中Ai 与Ai+1是可乘的,i =1,2,...,n-1。

考察这n 个矩阵的连乘积A 1A2...An ,给出其最优计算次序,使矩阵连乘运算数乘次数最少。

实验要求:
1. 理解动态规划算法的原理,认真阅读题目。

完善程序,实现该算法;
2. 给定五个矩阵:A1:5*10;A2:10*4;
A3:4*6; A4:6*10;A5:10*2,给出最优计算次序和数乘次数。

实验提示:
设计算A[i:j],1≤i ≤j ≤n ,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n]。

递归定义m [i ,j ]为:
public static void matrixChain(int [] p, int [][] m, int [][] s)
{ int n=p.length-1;
for (int i = 1; i <= n; i++) m[i][i] = 0;
for (int r = 2; r <= n; r++)
for (int i = 1; i <= n - r+1; i++) {
int j=i+r-1;
m[i][j] = m[i+1][j]+ p[i-1]*p[i]*p[j];
s[i][j] = i;
for (int k = i+1; k < j; k++) {
int t = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
if (t < m[i][j]) { m[i][j] = t; s[i][j] = k; }
}
}
}
实验题目4:0-1背包问题
给定n 种物品和一背包。

物品i 的重量是wi ,其价值为vi ,背包的容量为C 。

问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
实验要求:
1. 理解动态规划算法的原理,认真阅读题目。

完善程序,实现该算法;
2. 输入数据: 5个物品的重量分别是{2, 2, 6, 5, 4},价值分别为{6, 3, 5, 4, 6},背包的容量为10。

3.输出:背包能装的最大价值、背包装下的物品编号
实验提示:
设n个物品的重量存储在数组w[n]中,价值存储在数组v[n]中,背包容量为C,数组V[n+1][C+1]存放迭代结果,其中V[i][j]表示前i个物品装入容量为j的背包中获得的最大价值,数组x[n]存储装入背包的物品,动态规划法求解0/1背包问题的算法如下:
public static int KnapSack(int C, int w[ ], int v[ ],int[][]V, int[] x)
{ int n = v.length-1;
for (int i = 0; i <= n; i++) V[i][0] = 0; // 初始化第0列
for (int j = 0; j <= C; j++) V[0][j] = 0; // 初始化第0行
for (int i = 1; i <= n; i++)
// 计算第i行,进行第i次迭代
for (int j = 1; j <= C; j++)
if (j < w[i]) V[i][j] = V[i - 1][j];
else V[i][j] = Math.max(V[i - 1][j], V[i - 1][j - w[i]] + v[i]);
int j = C; // 求装入背包的物品
for (int i = n; i > 0; i--) {
if (V[i][j] > V[i - 1][j]) {
x[i] = 1; //第i号物品装入背包
j -= w[i];
} else x[i] = 0; //第i号物品没有装入背包
}
return V[n][C]; // 返回背包取得的最大价值
}
代码:
package test3;
public class test3 {
//最长公共子序列问题
public static int lcsLength(char [ ]x,char [ ]y,int [ ][ ]b)
{ int m=x.length-1;
int n=y.length-1;
int [][]c=new int [m+1][n+1];
for (int i = 1; i <= m; i++) c[i][0]=0;
for (int i = 1; i <= n; i++) c[0][i]=0;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++) {
if (x[i] == y[j]) { c[i][j]=c[i-1][j-1]+1; b[i][j]=1;}
else if (c[i-1][j]>=c[i][j-1]) { c[i][j]=c[i-1][j]; b[i][j]=2;}
else { c[i][j]=c[i][j-1]; b[i][j]=3;}
}
for(int i=0;i<=m;i++)
{
for(int k=0;k<=n;k++)
{
System.out.print(c[i][k]+" ");
}
System.out.println();
}
return c[m][n];
}
public static void lcs(int i,int j,char [] x,int [][] b)
{ if (i == 0 || j == 0) return;
if (b[i][j] == 1){
lcs(i-1,j-1,x,b);
System.out.print(x[i]);
}
else if (b[i][j] == 2) lcs(i-1,j,x,b); else lcs(i,j-1,x,b);
}
//0-1背包问题
public static int KnapSack(int C, int w[ ], int v[ ],int[][]V, int[] x)
{ int n = v.length-1;
for (int i = 0; i <= n; i++) V[i][0] = 0; // 初始化第0列
for (int j = 0; j <= C; j++) V[0][j] = 0; // 初始化第0行
for (int i = 1; i <= n; i++)
// 计算第i行,进行第i次迭代
for (int j = 1; j <= C; j++)
if (j < w[i]) V[i][j] = V[i - 1][j];
else V[i][j] = Math.max(V[i - 1][j], V[i - 1][j - w[i]] + v[i]);
int j = C; // 求装入背包的物品
for (int i = n; i > 0; i--) {
if (V[i][j] > V[i - 1][j]) {
x[i] = 1; //第i号物品装入背包
j -= w[i];
} else x[i] = 0; //第i号物品没有装入背包
}
for(int i=0;i<=v.length-1;i++)
{
for(int m=0;m<=C;m++)
{
System.out.print(V[i][m]+" ");
}
System.out.println();
}
System.out .print("放入背包的物品号:");
for (int i=0;i<x.length ;i++)
{
if (x[i] == 1)
{
System.out .print(i+" ");
}
}
return V[n][C];
}
public static void main(String[] args){
char []x = new char [10];
x = " xyxzyxyzzy".toCharArray();
char []y = new char [12];
y = " xzyzxyzxyzxy".toCharArray();
int [][]b = new int [x.length ][y.length ]; //System.out.print(x.length+" "+y.length);
lcsLength (x,y,b);
lcs (x.length -1,y.length -1,x,b);
System.out .println();
int []w = {0,2,2,6,5,4};
int []v = {0,6,3,5,4,6};
int c = 10;
int [][]result = new int [w.length ][c+1];
int []n = new int [w.length ];
KnapSack (c,w,v,result,n);
}
}
参考输入
1. 最长公共子序列 求y z z y x y z x y x A =,y x z y x z y x z y z x B =的最长公共子序列。

解 用两个)1()1(+⨯+m n 的表,来分别存放c[i][j]和状态b[i][j]。

c[i][j]的计算结果如下图所示。

由图中看到,最长公共子序列的长度为8。

0 1x 2z 3y 4z 5x 6y 7z 8x 9y 10z 11x 12y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1x 0 1 1 1 1 1 1 1 1 1 1 1 1 2y 0 1 1 2 2 2 2 2 2 2 2 2 2 3x 0 1 1 2 2 3 3 3 3 3 3 3 3 4z 0 1 2 2 3 3 3 4 4 4 4 4 4 5y 0 1 2 3 3 3 4 4 4 5 5 5 5 6x 0 1 2 3 3 4 4 4 5 5 5 6 6 7y 0 1 2 3 3 4 5 5 5 6 6 6 7 8z 0 1 2 3 4 4 5 6 6 6 7 7 7 9z 0 1 2 3 4 4 5 6 6 6 7 7 7 10y 0 1 2 3 4 4 5 6 6 7 7 7 8
最长公共子序列长度的计算例子
下图表示用b[i][j]搜索公共子序列的过程。

公共子序列是y z y x z x y x
a
a
a
a
a
a
a
a
10
8
7
6
4
3
2
1。

最长公共子序列字符的搜索过程
2.0-1背包问题
有5个物品,其重量分别是{2, 2, 6, 5, 4},价值分别为{6, 3, 5, 4, 6},背包的容量为10。

根据动态规划函数,用一个(n+1)×(C+1)的二维表V,V[i][j]表示把前i个物品装入容量为j的背包中获得的最大价值。

相关文档
最新文档