当前位置:城玮文档网 >作文大全 > 实验二动态规划算法

实验二动态规划算法

时间:2022-08-03 17:35:03 来源:网友投稿

 实验 二 动态规划算法

  基本题一:最长公共子序列问题 一、实验目的与要求 1 1 、熟悉最长公共子序列问题的算法; 2 2 、初步掌握动态规划算法; 二、实验题

  若给定序列 X={x1,x2, … ,xm} ,则另一序列 Z={z1,z2, … ,zk} ,是 X X 的子序列是指存在一个严格递增下标序列 {i1,i2, … ,ik} 使得对于所有 j=1,2, …k ,k 有:

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

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

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

  三. (1) 实验源代码: : // 最长公共子序问题: : // 问题描述 :

 若给定序列 X={x1,x2, … ,xm} ,则另一序列 Z={z1,z2, … ,zk} , //是 是 X X 的子序列是指存在一个严格递增下标序列 {i1,i2, … ,ik} 使得对于所有j=1,2, …k ,k 有:

 zj=xij 。

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

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

 Z Z 是序列 X X 和 和 Y Y 的公共子序列。

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

 #include<bits/stdc++.h> using namespace std; #define max 1000

 // 注意:这里使用的 r char 数组,可以按字符输出,若改为 g string 类型, // 执行 printf("%c",A[m- - 1]) 就会报错; ;

  char A[100],B[100];

 // 输入的两个串 a a 和 和 b b

 // 这里定义全局变量可以不赋值 0 0 ,因为全局变量自动赋值 0;

 int c[max][max]; // 记录最长公共子序的长度;

  int b[max][max]; // 记录状态号;

  void LCS(int m,int n) { {

  if(m==0||n==0)

  { {

  return;

  } }

  else if(b[m][n]==1)

  { {

 LCS(m- - 1,n- - 1);

  printf("%c",A[m- - 1]);

 } }

  els e if(b[m][n]==2)

  { {

  m=m- -; 1;

  LCS(m,n);

  } }

  else if(b[m][n]==3)

  { {

  n=n- -; 1;

  LCS(m,n);

  } } } }

 void LCS_length(int m,int n) { {

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

  { {

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

  { {

  if(A[i- - 1]==B[j- - 1])

  { {

 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;

  } }

  } }

  } }

  } }

  int main() { {

  printf(" 请输入两个待测的字符串: :\ \ n");

  scanf("%s",&A);

 scanf("%s",&B);

 int m=strlen(A);

 //m 为 为 A A 串长度;

  n int n=strlen(B);

 //n 为 为 B B 串长度;

  LCS_length(m,n);

  printf(" 其最长公共子序的长度为 :%d\ \ n",c[m][n]);

 printf(" 其最长公共子序为 :");

  LCS(m,n);

 return 0; } } (2) 运行结果为: :

 (3) 算法思路: : 最长公共子序列的结构有如下表示:

 设序列 X=<x 1 1 , x 2 2 , …, x m m > > 和 Y=<y 1 1 , y 2 2 , …, y n n > > 的一个最长公共子序列Z=<z 1 1 , z 2 2 , …, z k k > > ,则:

 1. 若 若 x x m m =y n n ,则 z z k k =x m m =y n n 且 Z Z k k- -1 1 是 是 X X m m- -1 1 和 和 Y Y n n- -1 1 ; 的最长公共子序列; 2. 若 若 x x m m ≠y n n 且 且 z z k k ≠x m , 则 Z Z 是 X X m m- -1 1 和 和 Y Y 的最长公共子序列; 3. 若 若 x x m m ≠y n n 且 且 z z k k ≠y n n

  ,则 Z Z 是 是 X X 和 和 Y Y n n- -1 1 的最长公共子序列。

 其中 X X m m- -1 1 =<x 1 1 , x 2 2 , …, x m m- -1 1 > >, ,Y Y n n- -1 1 =<y 1 1 , y 2 2 , …, y n n- -1 1 > >, ,Z Z k k- -1 1 =<z 1 1 , z 2 2 , …, z k k- -1 1 > >。

 。

 基本题二:最大字段和问题

  一、实验目的与要求 1 1 、熟悉最长最大字段和问题的算法; 2 2 、进一步掌握动态规划算法; 二、实验题 若给定 n n 个整数组成的序列 a a 1 1 ,a a 2 2 ,a a 3 3 ,……a a n n ,求该序列形如 a a i i +a a i i +1 1 +……+a a n n 的最大值。

 三,实验源代码: : #include<bits/stdc++.h> #define max 1000 using namespace std;

 int N;

 // 表示一个数组的长度值; ;

 int dp[max];

 // 记录以 i i 为结尾的最大子段和;

 // 通过 d dp p 数组记录最优下标的 t start 和 和 end;

  void Maxsum(int a[]) { {

  int maxx=0;

  int end,start;

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

  { {

  if(dp[i- - 1]>0)

  { {

  dp[i]=dp[i- - 1]+a[i];

  } }

  else

  { {

  dp[i]=a[i];

  } }

  if(maxx<=dp[i])

  { {

  maxx=dp[i];

  end=i;

  } }

 } }

 start=end;

  int i;

  for(i=start- - 1;i>=0;i- --) )

  { {

  if(dp[i]>=0)

  { {

  start=i;

  } }

  else

  { {

  break;

  } }

  } }

  i++;

  start=i;

  printf("MaxSum:%d\ \ n",dp[end]);

  printf("Best start:%d\ \ n",start);

  printf("Best end:%d\ \ n",end); } }

 int main() { {

  printf(" 请输入一组数据的元素个数 :");

  scanf( "%d",&N);

  int *a=new int [N+1];

 printf(" 请输入元素的值 :");

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

  { {

  scanf("%d",&a[i]);

  } }

 Maxsum(a);

  delete a;

  return 0; } } (2 2 )

 运行结果: :

  (3) 算法思路: : 其实,我们在选择一个元素 a[j] 的时候,只有两种情况,将 a[i]至 至 a[j- -] 1] 加上,或者从 从 a[j]以 以 j j 为起点开始。我们用一个数组 dp[i] 表示以 i i 为结束的最大子段和,对于每一个 [ a[] i] ,加上 dp[i- -] 1] 成为子段,或以 a[i] 开始成为新段的起点。因为我们只需要记录 p dp 值,所以复杂度是 O(n) 。

 这就是最大子段和的动态规划算法。

 我们甚至不需要 p dp 数组,只需要定义一个 p dp 变量,因为最后要求的 p dp 值也是最大的,所以我们可以在求 p dp 的时候更新为最大的。

 提高题一:

 用动态规划法求解 1 0/1 背包问题

 一、实验要求与目的 1、 、 掌握动态规划算法求解问题的一般特征和步骤。

 2、 、 使用动态规划法编程,求解 1 0/1 背包问题。

 二、实验内容 1、 、 问题描述:给定 n n 种物品和一个背包,物品 i i 的重 量是 W i i ,其价值为 V V i i ,问如何选择装入背包的物品,使得装入背包的物品的总价值最大? 2、 、 算法描述。

 3、 、 程序实现;给出实例测试结果。

  三 .(1) 实验源代码: : // 用动态规划的方法求解 1 0/1 背包问题 // 要求: : //input:n 表示总共有 n n 种物品 //

 W 表示每种物品的重量 //

 V 表示每种物品的价值 //

 c 表示背包的容量

  #include<bits/stdc++.h> using namespace std;

  int n,c; int dp[1005][1005; ];

 void Knapsack(int V[],int W[],int c,int n,int dp[][1005]) { {

  int i,j;

  int jMax=min(W[n]- - 1,c);

 // 这里必须是 W[n]- -, 1, 否则,在 W[n- -] 1] 时刻也是合法情况;

 for(j=0;j<=jMax;j++)

  { {

  dp[n][j]=0;

 //i=n,j<wn;

  } }

  for(j=W[n];j<=c;j++)

  { {

  dp[n][j]=V[n];

  } }

 for(i=n- -1 1 ;i>1;i- --) )

  { {

  jMax=min(W[i]- - 1,c);

 for(j=0;j<=jMax;j++)

  { {

 dp[i][j]=dp[i+1][j];

  // 若小于当前的背包容量,则不装入;

 } }

  for(j=W[i];j<=c;j++)

  { {

  dp[i][j]=max(dp[i+1][j],dp[i+1][j- - W[i]]+V[i]);

 // 比较装入的代价,谋求最大代价;

 } }

  } }

 dp[1][c]=dp[2][c];

  if(c>=W[1])

  { {

  dp[1][c]=max(dp[1][c],dp[2][c- - W[1]]+V[1]);

  } } } }

 void Traceback(int dp[][1005],int W[],int c,int n,int x[]) { {

  x //x 数组用来存放是否第 i i 个元素被装栽进来

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

  { {

  if(dp[i][c]==dp[i+1][c])

  { {

 x[i]=0;

  } }

  else

  { {

  x[i]=1;

  c=c- - W[i];

  } }

  }

  x x [n]=(dp[n][c])?1:0;

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

  { {

  if(x[i]==1)

  { {

  printf(" 第d %d 个物品装入\ \ n",i);

  } }

  } } } }

 int main() { {

  printf(" 请输入物品的数量和背包的容量 :");

  scanf("%d %d",&n,&c);

 int *W=new int [n];

  int *V=new int [n];

  int *x=new int [n];

  W[0]=0,V[0]=0,x[0]=0;

 printf(" 请输入每个物品的重量: :\ \ n");

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

  { {

  scanf("%d",&W[i]);

  } }

 printf(" 请输入每个物品的价值: :\ \ n");

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

  { {

  scanf("%d",&V[i]);

  } }

 Knapsack(V,W,c,n,dp);

  Traceback(dp,W,c,n,x);

  return 0; } } (2) 运行结果: :

  (3) 算法思路:

 令 V(i,j)表示在前 i(1<=i<=n)个物品中能够装入容量为就 j(1<=j<=C)的背包中的物品的最大价值,则可以得到如下的动态规划函数: (1)

  V(i,0)=V(0,j)=0

 (2)

  V(i,j)=V(i-1,j)

 j<w i

 V(i,j)=max{V(i-1,j) ,V(i-1,j-w i )+v i ) } j>w i

 (1)式表明:如果第 i 个物品的重量大于背包的容量,则装人前 i 个物品得到的最大价值和装入前 i-1 个物品得到的最大价是相同的,即物品 i 不能装入背包;第(2)个式子表明:如果第 i个物品的重量小于背包的容量,则会有一下两种情况:(a)如果把第 i 个物品装入背包,则背包物品的价值等于第 i-1 个物品装入容量位 j-w i

 的背包中的价值加上第 i 个物品的价值 v i;

 (b)如果第 i 个物品没有装入背包,则背包中物品价值就等于把前 i-1 个物品装入容量为 j 的背包中所取得的价值。显然,取二者中价值最大的作为把前 i 个物品装入容量为 j 的背包中的最优解。

相关热词搜索: 算法 实验 规划