实验二 动态规划算法.docx

上传人:b****6 文档编号:4442617 上传时间:2022-12-01 格式:DOCX 页数:12 大小:145.39KB
下载 相关 举报
实验二 动态规划算法.docx_第1页
第1页 / 共12页
实验二 动态规划算法.docx_第2页
第2页 / 共12页
实验二 动态规划算法.docx_第3页
第3页 / 共12页
实验二 动态规划算法.docx_第4页
第4页 / 共12页
实验二 动态规划算法.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

实验二 动态规划算法.docx

《实验二 动态规划算法.docx》由会员分享,可在线阅读,更多相关《实验二 动态规划算法.docx(12页珍藏版)》请在冰豆网上搜索。

实验二 动态规划算法.docx

实验二动态规划算法

实验二动态规划算法

 基本题一:

最长公共子序列问题

一、实验目的与要求

1、熟悉最长公共子序列问题的算法;

2、初步掌握动态规划算法;

二、实验题

   若给定序列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)实验源代码:

//最长公共子序问题:

//问题描述:

若给定序列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的最长公共子序列。

#include

usingnamespacestd;

#definemax1000

//注意:

这里使用的char数组,可以按字符输出,若改为string类型,

//执行printf("%c",A[m-1])就会报错;

charA[100],B[100];//输入的两个串a和b

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

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

intb[max][max];//记录状态号;

voidLCS(intm,intn)

{

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

{

return;

}

elseif(b[m][n]==1)

{

LCS(m-1,n-1);

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

}

elseif(b[m][n]==2)

{

m=m-1;

LCS(m,n);

}

elseif(b[m][n]==3)

{

n=n-1;

LCS(m,n);

}

}

voidLCS_length(intm,intn)

{

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

{

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

{

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

{

c[i][j]=c[i-1][j-1]+1;

b[i][j]=1;

}

elseif(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;

}

}

}

}

 

intmain()

{

printf("请输入两个待测的字符串:

\n");

scanf("%s",&A);

scanf("%s",&B);

intm=strlen(A);//m为A串长度;

intn=strlen(B);//n为B串长度;

LCS_length(m,n);

printf("其最长公共子序的长度为:

%d\n",c[m][n]);

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

");

LCS(m,n);

return0;

}

(2)运行结果为:

(3)算法思路:

最长公共子序列的结构有如下表示:

设序列X=和Y=的一个最长公共子序列Z=,则:

1.若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;

2.若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列;

3.若xm≠yn且zk≠yn ,则Z是X和Yn-1的最长公共子序列。

其中Xm-1=,Yn-1=,Zk-1=

基本题二:

最大字段和问题

 

一、实验目的与要求

1、熟悉最长最大字段和问题的算法;

2、进一步掌握动态规划算法;

二、实验题

若给定n个整数组成的序列a1,a2,a3,……an,求该序列形如ai+ai+1+……+an的最大值。

三,实验源代码:

#include

#definemax1000

usingnamespacestd;

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

intdp[max];//记录以i为结尾的最大子段和;

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

voidMaxsum(inta[])

{

intmaxx=0;

intend,start;

for(inti=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;

inti;

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("Beststart:

%d\n",start);

printf("Bestend:

%d\n",end);

}

intmain()

{

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

");

scanf("%d",&N);

int*a=newint[N+1];

printf("请输入元素的值:

");

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

{

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

}

Maxsum(a);

deletea;

return0;

}

(2)运行结果:

(3)算法思路:

其实,我们在选择一个元素a[j]的时候,只有两种情况,将a[i]至a[j-1]加上,或者从a[j]以j为起点开始。

我们用一个数组dp[i]表示以i为结束的最大子段和,对于每一个a[i],加上dp[i-1]成为子段,或以a[i]开始成为新段的起点。

因为我们只需要记录dp值,所以复杂度是O(n)。

 

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

 

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

 

提高题一:

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

一、实验要求与目的

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

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

二、实验内容

1、问题描述:

给定n种物品和一个背包,物品i的重量是Wi,其价值为Vi,问如何选择装入背包的物品,使得装入背包的物品的总价值最大?

2、算法描述。

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

 

三.

(1)实验源代码:

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

//要求:

//input:

n表示总共有n种物品

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

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

//c表示背包的容量

#include

usingnamespacestd;

intn,c;

intdp[1005][1005];

voidKnapsack(intV[],intW[],intc,intn,intdp[][1005])

{

inti,j;

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

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

{

dp[n][j]=0;//i=n,j

}

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

{

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

}

for(i=n-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]);

}

}

voidTraceback(intdp[][1005],intW[],intc,intn,intx[])

{

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

for(inti=1;i

{

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

{

x[i]=0;

}

else

{

x[i]=1;

c=c-W[i];

}

}

x[n]=(dp[n][c])?

1:

0;

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

{

if(x[i]==1)

{

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

}

}

}

intmain()

{

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

");

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

int*W=newint[n];

int*V=newint[n];

int*x=newint[n];

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

printf("请输入每个物品的重量:

\n");

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

{

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

}

printf("请输入每个物品的价值:

\n");

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

{

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

}

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

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

return0;

}

(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

    V(i,j)=max{V(i-1,j),V(i-1,j-wi)+vi)}j>wi

(1)式表明:

如果第i个物品的重量大于背包的容量,则装人前i个物品得到的最大价值和装入前i-1个物品得到的最大价是相同的,即物品i不能装入背包;第

(2)个式子表明:

如果第i个物品的重量小于背包的容量,则会有一下两种情况:

(a)如果把第i个物品装入背包,则背包物品的价值等于第i-1个物品装入容量位j-wi 的背包中的价值加上第i个物品的价值vi; (b)如果第i个物品没有装入背包,则背包中物品价值就等于把前i-1个物品装入容量为j的背包中所取得的价值。

显然,取二者中价值最大的作为把前i个物品装入容量为j的背包中的最优解。

 

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高中教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1