算法课程设计.docx
《算法课程设计.docx》由会员分享,可在线阅读,更多相关《算法课程设计.docx(28页珍藏版)》请在冰豆网上搜索。
算法课程设计
题目一数塔问题
问题描述:
有如右图所示的数塔,从顶部出发,在每一结点可以选择向左走或是向右走,一起走到底层,要求找出一条路径,使路径上的值最大
解决问题所用的方法:
动态规划
为了求得数塔1的解。
我们将数塔1分解为如下的数塔1顶点、数塔2和数塔3
数塔1的解=数塔1的顶点+数塔2解与数塔3解的最大值,同理,我们也将数塔2和数塔3分解为更小的数塔4、数塔5、数塔6和数塔7
……………
当数塔不可再分(仅有一层)时,就是分治的最小单元。
现运用动态规划的思想,自底向上求解,并将中间果存储想来以便以后再用。
A(1……n,1……n)表示数塔各层数的数字
B(1……n,1,……n)用来存储中间结果
基于分治的方法,得到递推公式如下:
注:
i=1……n,j=1……i
自底向上求解该问题.
算法描述:
算法名称:
MAXVALUE
输入:
树塔的层数n和各层的数字A[n][n]
输出:
最大值和路径C[n]
算法实现细节(可以用流程图,伪代码):
1.fori←1ton
2.B[n,i]←A[n,i]comment:
最下面一层为A[n,j]
3.endfor
4.fori←n-1to1
5.forj←1toi+1
6.B[i,j]←max{B[i+1,j],B[i+1,j+1]}+A[i,j]
7.comment:
B[i,j]等于下面它下面两个数的最大值加上A[i,j]
8.endfor
9.endfor
10.k←1
11.C[1]←1
12.fori←2ton
13.ifB[i,k+1]>B[i,k]thenk←k+1
14.comment:
寻找路径,找它下面两个数中最大一个的下标并记录
15.endif
16.C[i]←k
17.endfor
18.returnB[1,1]comment:
返回最大路径的值
算法的时间复杂度
算法实例:
数据的输入(可以有屏幕截图)
数据的输出(可以有屏幕截图)
题目二校园导航问题
问题描述:
设计你所在学校的平面图,至少包括10个以上的场所,每两个场所间可以有不同的路,且路长也可能不同,找出从任意场所到达另一场所的最佳路径(最短路径)。
解决问题所用的方法:
贪心算法
校园导航问题为最短路径问题。
设G=(V,E)是一个每条边有非负长度的无向图,有一点s称为源点,校园导航问题就是要确定从s到V中的一个顶点x的的最短距离。
初始时,将顶点集合分为两个集合B={s},C={1……s-1,s+1……n},每一步中,我们选定源点到它的距离已经得到的一个顶点c
C,并将它移入B中。
与C中的每个顶点c联系的是标记D[c],它是只经过B中顶点的最短路径,一旦顶点c
C移到B中,与c相邻的每个顶点
C的标记就会被更新。
这表示找到了经过c到
的更短路径。
当x
C被移入B中时,x的标记就是从源s到顶点x的最短路径。
为了方便找出具体的的最短图径,我们将标记矩阵定义为
二维矩阵D,第x列的最小值就是源s到顶点x的最小路径。
A(1……n,1……n)为无向图的邻接矩阵,我们寻找顶点s到s的最短路径无意义,我们将它到本身的距离定义为无穷大(只是为了方便)如下图:
寻找最短路径时,我们选找顶点x列的最小值的行标i,若i不等于s,则再找第i列的最小值所在的行标j,依次下去,直到行标为s时,这条路径就是最短路径。
算法描述:
算法名称:
FINDMIN
输入:
地点的个数n之间的距离A[i,j],以及起始点a和终点b
输出:
最短路径值和其路径
算法实现细节(可以用流程图,伪代码):
1.fori←1ton
2.C[i]←0comment:
初始化路径
3.endfor
4.fori←1ton
5.B[i]←1comment:
B[i]记录地点i是否可用
6.endfor
7.forj←1ton
8.D[i,j]←
9.endfor
10.k←a
11.min←0
12.whilek≠b
13.fori←1ton
14.ifA[k,i]≠
15.thenD[k,j]←A[k,j]+min
16.comment:
如果A[k,j]不为无穷,则D[k,j]等于A[k,j]加上最小值
17.endif
18.min←
19.forj←1ton
20.ifB[j]=0thencontinue
21.endif
22.fori←1ton
23.ifD[i,j]寻找a点到可用地点的最小值
24.thenmin←D[i,j]
25.l←j
26.endif
27.endfor
28.endfor
29.k←l
30.endwhile
31.min←
32.forj←0toncomment:
寻找最小路径的值
33.min←min{min,D[j,b]}
34.endfor
35.k<-b
36.i<-1
37.whilek≠a
38.l←
39.C[i]←k
40.i←i+1
41.forj←0ton
42.ifl>D[j,k]
43.thend←j
44.l←D[j,k]comment:
寻找最短的路径
45.endif
46.endfor
47.k←d
48.endwhile
49.C[i]←k
50.ifa=bthenreturn0
51.elsereturnmin
52.endif
算法的时间复杂度:
算法实例:
数据的输入(可以有屏幕截图)
数据的输出(可以有屏幕截图)
题目三货物装车问题
问题描述:
在杂货店中有n种不同的货物。
现将货物装车,规定从每种货物中最多只能拿一件,车子的容量为c,物品i需占用wi的空间,价值为pi。
现要求设计算法和程序使车中装载的物品价值最大。
当然,所装货物不能超过车的容量,且同一种物品不得拿走多件
解决问题所用的方法:
动态规划
W(1……n)表示物品所占用的空间
P((1……n)表示物品的价值
V[i,j]表示从前i个物品取出来放入容积为j的货车上的最大价值。
i=0……n,j=0……c
当i或j等于0时,V[0,0]等于0
如果第i个物体的体积大于车的容积,则V[i,j]=V[i-1,j]
如果第i个物体的体积不大于车的容积,则V[i,j]=V[i-1,j]与V[i-1,j-W[i]]+P[i]的最大值
我们得到公式:
运用动态动态规划的方法求解
算法描述:
算法名称:
BAGMAX
输入:
物品的个数,货车的最大容量,每件货物应的体积和价值
输出:
可拿的最大价值以及该拿的货物
算法实现细节(可以用流程图,伪代码):
1.fori←0ton
2.V[i,1]←0
3.endfor
4.fori←0toc
5.V[1,i]←0
6.endfor
7.fori←1ton
8.forj←1toc
9.ifw[i]>jthenV[i][j]←V[i-1][j]
10.elseV[i][j]←max{V[i-1][j],V[i-1,j-W[i-1]]+P[i-1]}
11.comment:
计算相应的值
12.endif
13.endfor
14.endfor
15.j←c
16.k←1
17.fori←nto0
18.ifV[i][j]=V[i-1]thenL[k]←i
19.k←k+1
20.j←j-W[i]comment:
找出应该拿的物品
21.endif
22.endfor
23.returnV[n,c]
算法的时间复杂度
算法实例:
数据的输入(可以有屏幕截图)
数据的输出(可以有屏幕截图)
题目四party幸运人士
问题描述:
一次大型的party最后节目是选取一位幸运人士,该人将获得组织者准备的一个钻石戒指。
选择办法是让所有人一字排列,然后从左至右点数,凡是奇数号的全部删除。
对剩下的人,同样从左至右点数,逢奇数号就删除。
如此不断循环,直到只剩1人为止。
此即为幸运之
解决问题所用的方法:
归纳法
算法描述:
算法名称:
LUCKY
输入:
参加Party的人数
输出:
幸运号码
算法实现细节(可以用流程图,伪代码):
1.fori←1ton
2.PM[i]←i
3.endfor
4.whilen>1
5.k←1
6.fori←1ton
7.ifi不能被2整除
8.thenPM[k]←PM[i]
9.k←k+1
10.endif
11.endfor
12.n←k-1
13.endwhile
14.returnPM[1]
算法的时间复杂度
算法实例:
数据的输入输出(可以有屏幕截图)
题目五找零问题
问题描述:
假设你在餐馆吃饭花了不到100元,结账时你给服务员一张百元钞票,而服务员希望用最少的纸币给你找钱。
请设计算法帮助服务员
解决问题所用的方法:
贪心算法
算法描述:
算法名称:
CHANGE
输入:
消费的钱money
输出:
总的钱的张数和每种面额钱的张数
算法实现细节(可以用流程图,伪代码):
1.tM←100-money
2.k←0
3.fori←1to9
4.M[i]←tM/MM[i]comment:
MM表示各种面额的钱
5.tM←tM-M[i]*MM[i]
6.k←k+M[i]
7.endfor
8.returnk
算法的时间复杂度
算法实例:
数据的输入输出(可以有屏幕截图)
课程设计总结
算法是计算机理论和实践的核心,通过这次的课程设计,让我认识到算法的重要性。
学好算法对以后的学习有很大的帮助,特别是对程序开发等方面上有着举足轻重的作用。
这次的课程设计,共完成了5个题目,充分运用了归纳法、分治、贪心等方法对题目进行分析,并用C语言将之实现。
通过这次比较完整的一个程序的设计,我摆脱了单纯的理论知识学习状态,和实际设计的结合锻炼了我的综合运用所学的墓础知识,解决实际问题的能力,同时也提高我查阅文献资料、对程序整体的把握等其他能力水平,而且通过对整体的掌控,对局部的取舍,以及对细节的斟酌处理,都使我的能力得到了锻炼,经验得到了丰富。
这是我们都希望看到的也正是我们进行课程设计的目的所在。
虽然设计内容繁多,过程繁琐但我的收获却更加丰富。
和老师以及同学的沟通交流更使我对程序整体的规划与设计有了新的认识也对自己提出了新的要求提高是有限的但提高也是全面的,正是这一次设计让我积累了许多实际经验,也必然会让我在未来的工作学习中表现出更高的应变能力和理解力。
参考文献
[1]张建勋纪纲《C程序设计实用教程》中国铁道出版社2009年1月第1版
[2]吴伟昶方世昌《算法设计技巧与分析》电子工业出版社2010.10
源码:
//用动态规划法求解数塔问题.cpp:
定义控制台应用程序的入口点。
//
#include"stdio.h"
#include
usingnamespacestd;
#defineN20
intA[N][N];
intB[N][N];
intC[N];
intmaxValue(intn)
{
inti,j;
for(i=0;iB[n-1][i]=A[n-1][i];
for(i=n-2;i>=0;i--)//计算其它层
{
for(j=0;j<=i;j++)
{
if(B[i+1][j]>B[i+1][j+1])
B[i][j]=B[i+1][j]+A[i][j];
else
B[i][j]=B[i+1][j+1]+A[i][j];
}
}
intk=0;
C[0]=0;
for(i=1;i{
if(B[i][k+1]>B[i][k])
k++;
C[i]=k;
}
returnB[0][0];
}
voidmain()
{
inti,j,n;
cout<<"请输入数塔的层数";
cin>>n;
for(i=0;i{
for(j=0;j<=i;j++)
{
cout<<"请输入第"<
cin>>A[i][j];
}
}
i=maxValue(n);
cout<<"最大值为:
"<
for(i=0;i{
cout<<"第"<";
}
cout<<"第"<
}
//背包问题.cpp:
定义控制台应用程序的入口点。
//
#include"stdio.h"
#include
usingnamespacestd;
#defineN200
#defineC1000
intW[N];
intP[N];
intL[N];
intBagMax(intn,intc)
{
inti,j,k=0;
intV[N][C];
for(i=0;i<=n;i++)
V[i][0]=0;
for(i=1;i<=c;i++)
V[0][i]=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=c;j++)
{
if(W[i-1]>j)
V[i][j]=V[i-1][j];
else
{
if((P[i-1]+V[i-1][j-W[i-1]])V[i][j]=V[i-1][j];
else
V[i][j]=P[i-1]+V[i-1][j-W[i-1]];
}
}
}
j=c;
for(i=n;i>=0;i--)
{
if(V[i][j]!
=V[i-1][j])
{
L[k]=i;
k++;
j=j-W[i-1];
}
}
returnV[n][c];
}
voidmain()
{
inti,n,c;
cout<<"请输入物品的个数:
";
cin>>n;
cout<<"请输入货车的容积:
";
cin>>c;
for(i=0;i{
cout<<"请输入第"<
";
cin>>W[i];
cout<<"请输入第"<
";
cin>>P[i];
}
i=BagMax(n,c);
cout<<"可以装货的最大价值为:
"<
cout<<"其中拿货方案为:
"<for(i=0;L[i]!
=0;i++)
{
cout<<"第"<}
cout<}
//校园导航问题.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include
usingnamespacestd;
#defineN20
charname[N][20];
intA[N][N];
intD[N][N];
intB[N];
intC[N];
intmenu(intn)
{
inti;
system("cls");
cout<<"__________________________________________________"<cout<<"校园导航软件"<for(i=0;i{
cout<<""<
"<}
i=0;
cout<<"__________________________________________________"<while(i<=0||i>n)
{
cout<cin>>i;
}
returni-1;
}
intinput()
{
inti,j,n=0;
while(n>20||n<=0)
{
cout<<"请输入地点的个数(小于20)";
cin>>n;
}
cout<for(i=0;i{
cout<<"请输入第"<
cin>>name[i];
}
for(i=0;i{
A[i][i]=RAND_MAX;
for(j=i+1;j{
cout<<"请输入"<cout<<"如果不相邻,则输入0(负数)距离为";
cin>>A[i][j];
if(A[i][j]<=0)
A[i][j]=RAND_MAX;
A[j][i]=A[i][j];
}
}
returnn;
}
intfind(inta,intb,intn)
{
intk=a,min=0,l=a,i,j,d=b;
for(i=0;iC[i]=-1;
if(a==b)
return0;
for(i=0;i{
B[i]=i;
for(j=0;jD[i][j]=RAND_MAX;
}
while(k!
=b)
{
for(j=0;j{
if(A[k][j]!
=RAND_MAX)
D[k][j]=A[k][j]+min;
}
B[k]=-1;
min=RAND_MAX;
for(j=0;j{
if(B[j]==-1)
continue;
for(i=0;i{
if(D[i][j]{
min=D[i][j];
l=j;
}
}
}
k=l;
}
min=RAND_MAX;
for(j=0;j{
if(D[j][b]{
min=D[j][b];
}
}
k=b;
i=0;
C[i]=k;
while(k!
=a)
{
l=RAND_MAX;
C[i]=k;
i++;
for(j=0;j{
if(l>D[j][k])
{
d=j;
l=D[j][k];
}
}
k=d;
}
C[i]=k;
returnmin;
}
voidmain()
{
intn=input();
inta=menu(n),b=menu(n);
system("cls");
inti=find(a,b,n);
cout<cout<
cout<<"最短路径为";
for(i=n-1;i>0;i--)
{
if(C[i]==-1)
continue;
cout<";
}
cout<}
//餐厅找零问题.cpp:
定义控制台应用程序的入口点。
//
#include"stdio.h"
#include
usingnamespacestd;
intM[9];
intMM[9]={500,200,100,50,20,10,5,2,1};
intchange(floatmoney)
{
inttM=10*(100-money);
inti=0,k=0;
if(money>100||money<=0)
return-1;
for(i=0;i<9;i++)
M[i]=0;
for(i=0;i<9;i++)
{
M[i]=tM/MM[i];
tM=tM-M[i]*MM[i];
k+=M[i];
}
returnk;
}
voidmain()
{
floatm;
intk,i;
cout<<"请输入你消费了多少钱:
";
cin>>m;
k=change(m);
cout<<"一共找你"<for(i=0;i<6;i++)
{
if(M[i]==0)
continue;
cout<}
for(i=6;i<9;i++)
{
if(M[i]==0)
continue;
cout<}
}
//party幸运人士.cpp:
定义控制台应用程序的入口点。
//
#include"stdio.h"
#include
usingnamespa