实验报告余双.docx
- 文档编号:20897409
- 上传时间:2023-04-25
- 格式:DOCX
- 页数:24
- 大小:167.76KB
实验报告余双.docx
《实验报告余双.docx》由会员分享,可在线阅读,更多相关《实验报告余双.docx(24页珍藏版)》请在冰豆网上搜索。
实验报告余双
实验编号:
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;i j=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;k inttemp; temp=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]; if(temp m[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;i d[i]=newint[n]; } cout<<"请输入每一个数: "< for(i=0;i for(j=0;j<=i;j++){ cin>>d[i][j]; } } intmax=MaxSum(0,0); cout<<"求得的最大路径的和值为: "< } 运行结果: 四: 实验结果的分析与评价(该部分如不够填写,请另加附页) 注: 实验成绩等级分为(90-100分)优,(80-89分)良,(70-79分)中,(60-69分)及格,(59分)不及格。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 报告