实验报告余双.docx
《实验报告余双.docx》由会员分享,可在线阅读,更多相关《实验报告余双.docx(24页珍藏版)》请在冰豆网上搜索。
![实验报告余双.docx](https://file1.bdocx.com/fileroot1/2023-4/25/1e09e746-892c-4922-bd12-dce59453cb7d/1e09e746-892c-4922-bd12-dce59453cb7d1.gif)
实验报告余双
实验编号:
3四川师大《算法设计与分析》实验报告2016年5月1日
计算机科学学院14级4班实验名称:
动态规划及其应用
姓名:
余双学号:
2014110451指导老师:
__苏菡__实验成绩:
_____
实验一动态规划及其应用
一.实验目的及要求
目的要求:
(1)理解动态规划算法的概念和基本要素,并能和分治法进行比较。
(2)掌握设计动态规划算法的步骤,并编程实现有关算法。
(3)理解这样一个观点:
同样的问题可以用不同的方法解决,一个好的算法是反复努力和重新修正的结果。
二.实验内容
(1)编程实现矩阵连乘问题的求解。
(2)编程实现最大子段和问题的求解(分别采用分治法和动态规划法求解)。
(3)编程实现0-1背包问题的求解。
(4)设计一个O(n2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
(5)编程实现最长公共子序列(LCS)问题的求解。
(6)设计算法求解数字三角形问题,并编程实现。
(P80算法实现题3-4)
(7)设计算法求解独立任务最优调度问题,并编程实现。
问题描述:
欧诺个2台处理机A和B处理n个作业。
设第i个作业交给机器A处理时需要时间ai,若由机器B来处理,则需要时间bi。
由于各作业的特点和机器的性能关系,很可能对于某些i,有ai>=bi,而对于某些j,j不等于i,有aj设计一个动态规划算法,是的这2台机器处理完这n个作业的时间最短(从任何一台机器开工到最后一台机器停工的总时间)。
研究一个实例:
(a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2);(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4)
如:
(8)设计算法求解最少硬币问题,并编程实现。
注:
至少选择其中3题完成。
主要仪器设备及软件
(1)PC机
(2)TC、VC++、Java等任一编程语言
三.实验主要流程、基本操作或核心代码、算法片段(该部分如不够填写,请另加附页)
(1)编程实现矩阵连乘问题的求解。
程序代码:
main.cpp
#include
#include"head.h"
usingnamespacestd;
intmain()
{
inti,n,*p;
cout<<"请输入矩阵的个数:
"<cin>>n;
p=newint[n+1];
cout<<"请输入矩阵的维数(相邻矩阵的行列相等,只输入一次就行!
)";
for(i=0;i<=n;i++){
cin>>p[i];
}
int**m,**s;
m=newint*[n+1];
s=newint*[n+1];
for(i=1;i<=n;i++){
m[i]=newint[n+1];
s[i]=newint[n+1];
}
MatrixChain(p,n,m,s);
TraceBack(1,n,s);
return0;
}
MatrixChain.cpp
#include
#include"head.h"
usingnamespacestd;
voidMatrixChain(int*p,intn,int**m,int**s){
inti,j,r,k;
for(i=1;i<=n;i++){
m[i][i]=0;
s[i][i]=0;
}
for(r=2;r<=n;r++){
for(i=1;ij=i+r-1;
if(j<7){
m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(k=i+1;kinttemp;
temp=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(tempm[i][j]=temp;
s[i][j]=k;
}
}
}
}
}
}
TraceBack.cpp
#include
#include"head.h"
usingnamespacestd;
voidTraceBack(inti,intj,int**s){
if(i==j){
return;
}
TraceBack(i,s[i][j],s);
TraceBack(s[i][j]+1,j,s);
cout<<"MultiplyA"<
}
head.h:
#ifndefHEAD_H_INCLUDED
#defineHEAD_H_INCLUDED
voidMatrixChain(int*p,intn,int**m,int**s);
voidTraceBack(inti,intj,int**s);
#endif//HEAD_H_INCLUDED
运行结果:
(2)编程实现最大子段和问题的求解(分别采用分治法和动态规划法求解)。
分治法:
main.cpp:
#include
#include"head.h"
usingnamespacestd;
intmain(){
intn,i,*a;
cout<<"请输入序列长度:
"<cin>>n;
a=newint[n+1];
cout<<"请输入该序列具体的数:
";
for(i=1;i<=n;i++){
cin>>a[i];
}
intsum=MaxSubSum(1,n,a);
cout<<"该序列的最大字段和为:
"<}
MaxSubSum.cpp:
#include
#include"head.h"
intMaxSubSum(intleft,intright,int*a){
intsum=0;
if(left==right){
sum=a[left]>0?
a[left]:
0;
}
else{
intcenter=(left+right)/2;
intleftsum=MaxSubSum(left,center,a);
intrightsum=MaxSubSum(center+1,right,a);
ints1=0;intlefts=0;
for(inti=center;i>=left;i--){
lefts+=a[i];
if(lefts>s1){
s1=lefts;
}
}
ints2=0;intrights=0;
for(intj=center+1;j<=right;j++){
rights+=a[j];
if(rights>s2){
s2=rights;
}
}
sum=s1+s2;
if(leftsum>sum)sum=leftsum;
if(rightsum>sum)sum=rightsum;
}
returnsum;
}
head.h:
#ifndefH
#defineH
intMaxSubSum(intleft,intright,int*a);
#endif
运行结果:
动态规划法:
main.cpp
#include
#include"head.h"
usingnamespacestd;
intmain(){
intn,i,*a;
cout<<"请输入序列长度:
"<cin>>n;
a=newint[n+1];
cout<<"请输入该序列具体的数:
";
for(i=1;i<=n;i++){
cin>>a[i];
}
intsum=MaxSubSum(n,a);
cout<<"该序列的最大字段和为:
"<}
MaxSubSum.cpp
#include
#include"head.h"
usingnamespacestd;
intMaxSubSum(intn,int*a){
intsum=0,b=0;
for(inti=1;i<=n;i++){
if(b>0)b+=a[i];
elseb=a[i];
if(b>sum)sum=b;
}
returnsum;
}
head.h:
#ifndefH
#defineH
intMaxSubSum(intn,int*a);
#endif
运行结果:
(3)编程实现0-1背包问题的求解
main.cpp:
#include
#include"head.h"
usingnamespacestd;
intmain(){
inti,n,c,*v,*w,**m;
cout<<"请输入物品个数:
"<cin>>n;
cout<<"请输入背包总容量:
"<cin>>c;
v=newint[n+1];
w=newint[n+1];
cout<<"请输入每个物品的价值:
"<for(i=1;i<=n;i++){
cin>>v[i];
}
cout<<"请输入每个物品的重量:
"<for(i=1;i<=n;i++){
cin>>w[i];
}
m=newint*[n+1];
for(i=0;i<=n;i++){
m[i]=newint[n+1];
}
package(n,c,v,w,m);
cout<<"物品装入背包的情况如下:
(0表示该物品未放入背包,1表示该物品放入了背包)"<traceBack(1,c,w,m,n);
}
package.cpp:
#include
#include"head.h"
usingnamespacestd;
voidpackage(intn,intc,int*v,int*w,int**m){
inti,j;
for(i=0;i<=n;i++){
m[i][0]=0;
}
for(j=0;j<=c;j++){
m[0][j]=0;
if(w[n]>j){
m[n][j]=0;
}else{
m[n][j]=v[n];
}
}
for(i=n-1;i>0;i--){
for(j=c;j>0;j--){
if(w[i]>j){
m[i][j]=m[i+1][j];
}elseif(m[i+1][j]m[i][j]=v[i]+m[i+1][j-w[i]];
}else{
m[i][j]=m[i+1][j];
}
}
}
}
traceBack.cpp:
#include
#include"head.h"
usingnamespacestd;
voidtraceBack(inti,intj,int*w,int**m,intn){
if(i==n){
if(w[i]<=j){
cout<<"物品"<
1"<}else{
cout<<"物品"<
0"<}
return;
}
if(m[i][j]==m[i+1][j]){
cout<<"物品"<
0"<i++;
traceBack(i,j,w,m,n);
}else{
cout<<"物品"<
1"<j-=w[i];
i++;
traceBack(i,j,w,m,n);
}
}
head.h:
#ifndefH
#defineH
voidpackage(intn,intc,int*v,int*w,int**m);
voidtraceBack(inti,intj,int*w,int**m,intn);
#endif
运行结果:
(4)设计一个O(n2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
程序代码:
main.cpp:
#include
#include"Sub.h"
usingnamespacestd;
intmain(){
intn,*a,*b,*c,i;
cout<<"请输入序列长度:
"<cin>>n;
a=newint[n+1];
b=newint[n+1];
c=newint[n+1];
cout<<"请输入该序列的每一个数:
"<for(i=1;i<=n;i++){
cin>>a[i];
}
b[n]=1;
Sub(n,a,b,c);
inttemp=b[1],j=1;
for(i=1;i<=n;i++){
if(temp
temp=b[i];
j=i;
}
}
cout<<"最长单调递增子序列长度为"<"<while(c[j]!
=j){
cout<j=c[j];
}
cout<}
sub.cpp:
#include
#include"Sub.h"
usingnamespacestd;
intSub(intn,int*a,int*b,int*c){
inti,k,j,temp,temp2;
for(i=n;i>0;i--){
temp=a[i];j=0;temp2=0;b[i]=1;
for(k=i+1;k<=n;k++){
if(a[i]temp2){
j=k;
temp=a[k];
temp2=b[k];
}
}
if(temp==a[i]){
b[i]=1;
c[i]=i;
}else{
b[i]=1+temp2;
c[i]=j;
}
}
return0;
}
sub.h:
#ifndefH
#defineH
intSub(intn,int*a,int*b,int*c);
#endif
运行结果:
(5)编程实现最长公共子序列(LCS)问题的求解
程序代码:
main.cpp:
#include
#include"head.h"
usingnamespacestd;
intmain()
{
char*x,*y;
intm,n;
cout<<"请输入第一个序列的长度:
"<cin>>m;
x=newchar[m+1];
cout<<"请输入第一个序列:
"<for(inti=1;i<=m;i++){
cin>>x[i];
}
cout<<"请输入第二个数序列长度:
"<cin>>n;
y=newchar[n+1];
cout<<"请输入第二个序列:
"<for(intj=1;j<=n;j++){
cin>>y[j];
}
int**c,**b;
c=newint*[m+1];
b=newint*[m+1];
for(intk=0;k<=m;k++){
c[k]=newint[n+1];
b[k]=newint[n+1];
}
LCSLegth(m,n,x,y,c,b);
char*z=newchar[c[m][n]+1];
LCS(m,n,x,b,z,c[m][n]);
cout<<"最长公共子序列如下:
"<for(i=1;i<=c[m][n];i++){
cout<}
cout<return0;
}
LCS.cpp:
#include
#include"head.h"
usingnamespacestd;
intLCS(inti,intj,char*x,int**b,char*z,intk){
if(i==0||j==0){
return0;
}elseif(b[i][j]==1){
z[k]=x[i];
i--;
j--;
LCS(i,j,x,b,z,k-1);
}else{
if(b[i][j]==2){
i--;
LCS(i,j,x,b,z,k);
}else{
j--;
LCS(i,j,x,b,z,k);
}
}
}
LCSLegth.cpp:
#include
#include"head.h"
usingnamespacestd;
intLCSLegth(intm,intn,char*x,char*y,int**c,int**b){
inti,j;
for(i=0;i<=m;i++)
c[i][0]=0;
for(j=0;j<=n;j++)
c[0][j]=0;
for(i=1;i<=m;i++){
for(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;
}
}
}
}
return0;
}
head.h:
#ifndefH
#defineH
intLCSLegth(intm,intn,char*x,char*y,int**c,int**b);
intLCS(inti,intj,char*,int**b,char*z,intk);
#endif
运行结果:
(6)设计算法求解数字三角形问题,并编程实现。
(P80算法实现题3-4)
程序代码:
#include
#include
usingnamespacestd;
intn,**d;
intMaxSum(inti,intj){
if(i==n-1){
returnd[i][j];
}else{
intSum1=MaxSum(i+1,j);
intSum2=MaxSum(i+1,j+1);
if(Sum1>Sum2){
returnSum1+d[i][j];
}else{
returnSum2+d[i][j];
}
}
}
intmain(){
//freopen("D:
\\VC\\MicrosoftVisualStudio\\MyProjects\\experiment_3\\Data3\\input.txt","r",stdin);
//freopen("D:
\VC\MicrosoftVisualStudio\MyProjects\experiment_3\Data3\\output.txt","w",stdout);
inti,j;
cout<<"请输入数字三角形的行数:
"<cin>>n;
d=newint*[n];
for(i=0;id[i]=newint[n];
}
cout<<"请输入每一个数:
"<for(i=0;ifor(j=0;j<=i;j++){
cin>>d[i][j];
}
}
intmax=MaxSum(0,0);
cout<<"求得的最大路径的和值为:
"<}
运行结果:
四:
实验结果的分析与评价(该部分如不够填写,请另加附页)
注:
实验成绩等级分为(90-100分)优,(80-89分)良,(70-79分)中,(60-69分)及格,(59分)不及格。