计算机算法实验2 动态规划算法 报告文档格式.docx
《计算机算法实验2 动态规划算法 报告文档格式.docx》由会员分享,可在线阅读,更多相关《计算机算法实验2 动态规划算法 报告文档格式.docx(11页珍藏版)》请在冰豆网上搜索。
3实验心得5
说明:
代码在后面
1实验目的与要求
1、熟悉最长公共子序列问题的算法
2、掌握动态规划算法求解问题的一般特征和步骤
3、熟悉最长最大字段和问题的算法
4、使用动态规划法编程,求解0/1背包问题
2实验内容
最长公共子序列问题
2.1.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的最长公共子序列。
2.1.2实验截图
可以修改序列1和2,这里预设为ABCBDAB和BDCABA:
如果修改预设为ABCBDAB和efghj,则没有公共子序列:
最大子段和问题
2.2.1问题概述
若给定n个整数组成的序列a1,a2,a3,……an,求该序列形如ai+ai+1+……+an的最大值。
2.2.2实验截图
选择书本列子,输入序列为-2,11,-4,13,-5,-2:
全输入正数:
全输入负数,最大为零:
用动态规划法求解0/1背包问题
2.3.1问题概述
给定n种物品和一个背包,物品i的重量是Wi,其价值为Vi,问如何选择装入背包的物品,使得装入背包的物品的总价值最大?
2.3.2实验截图
采用书本例子,输入物品重量价值等信息:
换另一组数据测试:
3实验心得
本次实验的主要内容是动态规划,涉及的题目为最长公共子序列、最大子段和及0/1背包问题。
通过这三个实验题,我对动态规划的理解又加深了一步。
动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。
不像搜索或数值计算那样,具有一个标准的数学表达式和明确清晰的解题方法。
动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。
虽然这几道题解决了,但我知道自己的理解还很有限,编程还不能脱离书本。
而且动态规划算法是算法里的很重要的一部分内容,很多问题都可以通过动态规划来解决。
所以以后还要继续深入理解,熟练运用。
1基本题一:
#include<
iostream>
string.h>
usingnamespacestd;
#defineMAXLEN100
voidLCSLength(char*x,char*y,intm,intn,intc[][MAXLEN],intb[][MAXLEN])
{
inti,j;
for(i=0;
i<
=m;
i++)
c[i][0]=0;
for(j=1;
j<
=n;
j++)
c[0][j]=0;
for(i=1;
{
for(j=1;
{
if(x[i-1]==y[j-1])
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]=0;
}
elseif(c[i-1][j]>
=c[i][j-1])
c[i][j]=c[i-1][j];
b[i][j]=1;
else
c[i][j]=c[i][j-1];
b[i][j]=-1;
}
}
}
voidPrintLCS(intb[][MAXLEN],char*x,inti,intj)
if(i==0||j==0)
return;
if(b[i][j]==0)
PrintLCS(b,x,i-1,j-1);
printf("
%c"
x[i-1]);
elseif(b[i][j]==1)
PrintLCS(b,x,i-1,j);
else
PrintLCS(b,x,i,j-1);
intmain(intargc,char**argv)
charx[MAXLEN]={"
ABCBDAB"
};
chary[MAXLEN]={"
BDCABA"
intb[MAXLEN][MAXLEN];
intc[MAXLEN][MAXLEN];
intm,n;
cout<
<
"
预设为ABCBDAB和BDCABA"
<
endl;
m=strlen(x);
n=strlen(y);
最长公共子序列为:
"
LCSLength(x,y,m,n,c,b);
PrintLCS(b,x,m,n);
return0;
2基本题二:
intmax_sum(inta[],intn,int*best_i,int*best_j)
{//*best_i表示最大子段和的起始下标
//*best_j表示最大子段和的终点下标
//i,j表示当前子段的起点和终点下标
intthis_sum[100];
intsum[100];
intmax=0;
this_sum[0]=0;
sum[0]=0;
*best_i=0;
*best_j=0;
i=1;
j++)
{if(this_sum[j-1]>
=0)//判断是否为负数
this_sum[j]=this_sum[j-1]+a[j];
else
{this_sum[j]=a[j];
i=j;
}
//如果子段和数组前一个大于下一个元素
if(this_sum[j]<
=sum[j-1])
sum[j]=sum[j-1];
//对当前子段和赋值
{sum[j]=this_sum[j];
*best_i=i;
*best_j=j;
max=sum[j];
}
returnmax;
}
voidmain()
{inti,j,n,a[100],t;
printf("
请输入数列的个数(<
99):
\n"
);
cin>
>
n;
请输入数列元素:
i++)
cin>
a[i];
i=j=1;
t=max_sum(a,n,&
i,&
j);
最大字段和是:
%d\n"
t);
字段起点是:
i);
字段结束点:
j);
3提高题一:
动态规划法求解0/1背包问题
#include<
iomanip>
intmin(intw,intc){inttemp;
if(w<
c)temp=w;
elsetemp=c;
returntemp;
intmax(intw,intc){
inttemp;
if(w>
voidknapsack(intv[],intw[],intc,intn,int**m)//求最优值
{
intjmax=min(w[n]-1,c);
for(intj=0;
=jmax;
j++)m[n][j]=0;
for(intjj=w[n];
jj<
=c;
jj++)m[n][jj]=v[n];
for(inti=n-1;
i>
1;
i--){//递归部分
jmax=min(w[i]-1,c);
for(intj=0;
j<
=jmax;
j++)m[i][j]=m[i+1][j];
for(intjj=w[i];
jj++)
m[i][jj]=max(m[i+1][jj],m[i+1][jj-w[i]]+v[i]);
m[1][c]=m[2][c];
if(c>
=w[1])
m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]);
cout<
最优值:
m[1][c]<
*******************************************"
inttraceback(int**m,intw[],intc,intn,intx[])//回代,求最优解
得到的一组最优解如下:
for(inti=1;
i<
n;
if(m[i][c]==m[i+1][c])x[i]=0;
else{x[i]=1;
c-=w[i];
x[n]=(m[n][c])?
1:
0;
for(inty=1;
y<
y++){cout<
setw(5)<
x[y];
returnx[n];
voidmain(){
intn,c;
int**m;
请输入物品个数和重量上限:
;
n>
c;
int*v=newint[n+1];
c