算法设计与分析报告1.docx
《算法设计与分析报告1.docx》由会员分享,可在线阅读,更多相关《算法设计与分析报告1.docx(14页珍藏版)》请在冰豆网上搜索。
算法设计与分析报告1
学生学号
0121510880508
实验课成绩
学生实验报告书
实验课程名称
算法设计与分析B实验
开课学院
计算机科学与技术学院
指导教师姓名
学生姓名
丁小兵
学生专业班级
软件学术1502
2015
--
2016
学年
第
2
学期
实验项目名称
分治法的应用
报告成绩
实验者
丁小兵
专业班级
软件学术1502
组别
同组者
完成日期
2017年5月10日
第一部分:
实验分析与设计(可加页)
一、实验目的和要求
1.目的
(1)基本掌握分治算法的原理。
(2)掌握递归算法及递归程序的设计。
(3)能用程序设计语言求解相关问题。
2.要求
(1)用分治法求解问题;
(2)分析算法的时间性能,设计实验程序验证分析结论。
二、分析与设计
1.了解用分治法求解的问题:
当要求解一个输入规模为n,且n的取值相当大的问题时,如果问题可以分成k个不同子集合,得到k个不同的可独立求解的子问题,其中1那末,对于这类问题分治法是十分有效的。
2.掌握分治法的一般控制流程。
DanC(p,q)
globaln,A[1:
n];integerm,p,q;//1pqn
ifSmall(p,q)thenreturnG(p,q);
elsem=Divide(p,q);//pmreturnCombine(DanC(p,m),DanC(m+1,q));
endif
endDanC
3.实验内容
仔细阅读备选实验的题目,设计序要的程满足正确性,代码中有关键的注释,书写格式清晰,简洁易懂,效率较高,利用C++的模板,设计的程序通用性好,适合各种合理输入,并能对不合理输入做出正确的提示。
中位数问题
问题描述
设X[0:
n-1]和Y[0:
n–1]为两个数组,每个数组中含有n个已排好序的数。
找出X和Y的2n个数的中位数。
编程任务
利用分治策略试设计一个O(logn)时间的算法求出这2n个数的中位数。
数据输入
由文件input.txt提供输入数据。
文件的第1行中有1个正整数n(n<=200),表示每个数组有n个数。
接下来的两行分别是X,Y数组的元素。
结果输出
程序运行结束时,将计算出的中位数输出到文件output.txt中。
输入文件示例
输出文件示例
input.txt
output.txt
3
51518
31421
14
三、主要仪器设备及耗材
1.安装了Windows10操作系统的PC机1台
2.PC机系统上安装了MicrosoftVisualStudio2013开发环境
第二部分:
实验过程和结果(可加页)
四、代码调试说明(调试手段、过程及结果分析)
调试主要内容为编写程序的语法正确性与否,程序逻辑的正确性与否。
F5:
启动调试;F11:
逐语句调试;F12:
逐过程调试;F9:
切换断点;ctrl+B:
新建断点等。
代码:
#include
#include
usingnamespacestd;
intmidNum(inta[],intn){
if(n%2==0){
return(a[n/2]+a[n/2-1])/2;
}
else
returna[n/2];
}
intmax(inta,intb){
if(a>=b){
returna;
}
else{
returnb;
}
}
intmin(inta,intb){
if(a<=b){
returna;
}
else{
returnb;
}
}
intgetmidNum(inta[],intb[],intn){
intm1,m2;
if(n<=0)
return-1;
if(n==1)
return(a[0]+b[0])/2;
if(n==2)
return(max(a[0],b[0])+min(a[1],b[1]))/2;
m1=midNum(a,n);
m2=midNum(b,n);
if(m1==m2){
returnm1;
}
if(m1if(n%2==0){
returngetmidNum(a+n/2-1,b,n/2+1);
}
else{
returngetmidNum(a+n/2,b,n/2+1);
}
}
else{
if(n%2==0){
returngetmidNum(b+n/2-1,a,n/2+1);
}
else{
returngetmidNum(b+n/2,a,n/2+1);
}
}
}
intmain()
{
/*
ofstreamoo("file1.txt",ios:
:
out);
if(!
oo)
{
cout<<"Error";
system("pause");
return1;
}
oo<<11;
oo.close();
*/
ifstreamii("file1.txt",ios:
:
in);
if(!
ii)
{
cout<<"wrong";
system("pause");
return1;
}
inti;
ii>>i;
//cout<
inta[10];
intb[10];
ints=0;
for(s=0;s
{
ii>>a[s];
}
for(s=0;s
{
ii>>b[s];
}
ii.close();
//cout<
intresult=getmidNum(a,b,i);
cout<ofstreamoo("file2.txt",ios:
:
out);
if(!
oo)
{
cout<<"Error";
system("pause");
return1;
}
oo<oo.close();
system("pause");
return0;
}
运行截图:
输入截图:
输出截图:
第三部分:
实验小结、收获与体会
这次实验主要是利用分治法来寻求中位数。
通过这次的实验,让我充分学习了分治法以及其相关知识点,给我提供了一个动手操作的机会,并且为了能够实现这个目的而努力。
当然,不否认这次的实验也是相当有难度的,毕竟感觉工作量挺大的,而且也确实有不少自己不明白的地方。
对于这次的实验来说,我通过努力了解了什么是分治法,而且,也懂得了如何利用代码实现分治法。
总而言之,这次我收获确实很大。
实验项目名称
动态规划算法
报告成绩
实验者
丁小兵
专业班级
软件学术1502
组别
同组者
完成日期
2017年5月10日
一、实验目的和要求
1.实验目的
(1)能用程序设计语言实现求解相关问题的算法;
(2)深刻掌握动态规划法的设计思想并能熟练运用;
(3)理解这样一个观点:
同样的问题可以用不同的方法解决,一个好的算法是反复努力和重新修正的结果。
2.实验要求
(1)用动态规划法求解问题;
分析算法的时间性能,设计实验程序验证分析结论
3.实验内容
(1)仔细阅读备选实验的题目,选择一个(可选多个)作为此次实验题目,设计的程序要满足正确性,代码中有关键的注释,书写格式清晰,简洁易懂,效率较高,利用C++的模板,设计的程序通用性好,适合各种合理输入,并能对不合理输入做出正确的提示。
(2)从以下题目中任选其一完成。
i.最大K乘积问题
问题描述
设I是一个n位十进制整数。
如果将I划分为k段,则可得到k个整数。
这k个整数的乘积称为I的一个k乘积。
试设计一个算法,对于给定的I和k,求出I的最大k乘积。
例如十进制整数1234划分为3段可有如下情形:
1×2×34=68
1×23×4=92
12×3×4=144
编程任务
对于给定的I和k,编程计算I的最大k乘积。
数据输入
输入的第1行中有2个正整数n和k。
正整数n是序列的长度;正整数k是分割的段数。
接下来的一行中是一个n位十进制整数。
(n<=10)
结果输出
计算出的最大k乘积。
输入文件示例
输出文件示例
input.txt
output.txt
32
312
62
4.分析设计
理解最优子结构的问题。
有一类问题的活动过程可以分成若干个阶段,而且在任一阶段后的行为依赖于该阶段的状态,与该阶段之前的过程如何达到这种状态的方式无关。
这类问题的解决是多阶段的决策过程。
在50年代,贝尔曼(RichardBellman)等人提出了解决这类问题的“最优化原理”,从而创建了最优化问题的一种新的算法设计方法-动态规划。
对于一个多阶段过程问题,是否可以分段实现最优决策,依赖于该问题是否有最优子结构性质,能否采用动态规划的方法,还要看该问题的子问题是否具有重叠性质。
最优子结构性质:
原问题的最优解包含了其子问题的最优解。
子问题重叠性质:
每次产生的子问题并不总是新问题,有些子问题被反复计算多次。
问题的最优子结构性质和子问题重叠性质是采用动态规划算法的两个基本要素。
(1)理解分段决策Bellman方程。
每一点最优都是上一点最优加上这段长度。
即当前最优只与上一步有关。
us初始值,uj第j段的最优值。
(2)一般方法
1)找出最优解的性质,并刻画其结构特征;
2)递归地定义最优值(写出动态规划方程);
3)以自底向上的方式计算出最优值;
4)根据计算最优值时得到的信息,构造一个最优解。
步骤1-3是动态规划算法的基本步骤。
在只需要求出最优值的情形,步骤4可以省略,步骤3中记录的信息也较少;若需要求出问题的一个最优解,则必须执行步骤4,步骤3中记录的信息必须足够多以便构造最优解。
三、主要仪器设备及耗材
1.安装了Windows10操作系统的PC机1台
2.PC机系统上安装了MicrosoftVisualStudio2013开发环境
第二部分:
实验过程和结果(可加页)
四、代码调试说明(调试手段、过程及结果分析)
调试主要内容为编写程序的语法正确性与否,程序逻辑的正确性与否。
F5:
启动调试;F11:
逐语句调试;F12:
逐过程调试;F9:
切换断点;ctrl+B:
新建断点等。
代码:
#include
#include
#include
usingnamespacestd;
inta[101];//给定的n个数字
intm[101][101];//目标数组,储存最优解
intw[101][101];
intn,k;
intmax(inta,intb);
voidmaxdp()
{
inttemp,_max;
/*动态转移方程的求解过程
if(j==1)m(i,j)=w(1,i);
前i位(1:
i)数字分j组乘积的最大值等于分为j-1组的结果再乘以一个因子
if(j>=1&&j<=i)
m(i,j)=max{m(d,j-1)*m(d+1,i)}
其中:
1<=d
elseif(i*/
//如果分成1段
for(inti=1;i<=n;i++)
m[i][1]=w[1][i];
for(inti=1;i<=n;i++)
for(intj=2;j<=k;j++)
{
_max=0;
for(intd=1;d
{
m[i][j]=max(m[d][j-1]*w[d+1][i],m[i][j]);
if((m[d][j-1]*w[d+1][i])>_max)
_max=m[d][j-1]*w[d+1][i];
//cout<}
m[i][j]=_max;
}
}
intmax(inta,intb)
{
if(a>b)
{
returna;
}
else
returnb;
}
intmain()
{
system("pause");
ifstreami1("input.txt",ios:
:
in);
if(!
i1)
{
cout<<"Error";
system("pause");
return1;
}
intnum;
i1>>n>>k>>num;
inty=n;
for(intx=1;x<=n;x++)
{
y=y-1;
a[x]=num/(pow(10,y));
num=num-a[x]*(pow(10,y));
}
//w[i][j]表示从第i位到第j位所组成的十进制数
for(inti=1;i<=n;i++)
{
w[i][i]=a[i];
for(intj=i+1;j<=n;j++)
w[i][j]=w[i][j-1]*10+a[j];//每次乘以10再加上个位数
}
maxdp();
ofstreamo1("output.txt",ios:
:
out);
if(!
o1)
{
cout<<"ERROR";
system("pause");
return1;
}
o1<o1.close();
cout<//fprintf(fp2,"%I64d",m[n][k]);
//cout<system("pause");
return0;
}
运行截图:
输入截图:
输出截图:
第三部分:
实验小结、收获与体会
(4)这次实验主要是掌握动态规划法的设计思想并能熟练运用。
通过这次的实验,让我充分学习了动态规划法以及其相关知识点,给我提供了一个动手操作的机会,并且为了能够实现这个目的而努力。
当然,不否认这次的实验也是相当有难度的,毕竟感觉工作量挺大的,而且也确实有不少自己不明白的地方。
对于这次的实验来说,我通过努力了解了什么是分治法,而且,也懂得了如何利用代码实现动态规划法。
总而言之,这次我收获确实很大。