算法分析与设计课程设计报告Word文件下载.docx

上传人:b****5 文档编号:16973740 上传时间:2022-11-27 格式:DOCX 页数:23 大小:317.48KB
下载 相关 举报
算法分析与设计课程设计报告Word文件下载.docx_第1页
第1页 / 共23页
算法分析与设计课程设计报告Word文件下载.docx_第2页
第2页 / 共23页
算法分析与设计课程设计报告Word文件下载.docx_第3页
第3页 / 共23页
算法分析与设计课程设计报告Word文件下载.docx_第4页
第4页 / 共23页
算法分析与设计课程设计报告Word文件下载.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

算法分析与设计课程设计报告Word文件下载.docx

《算法分析与设计课程设计报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《算法分析与设计课程设计报告Word文件下载.docx(23页珍藏版)》请在冰豆网上搜索。

算法分析与设计课程设计报告Word文件下载.docx

根据计算最优值时得到的信息,构造最优解。

给定金额n以及1,2,5分硬币,求找n的最少硬币数。

对于大于1分的找零理所当然可以找零1分,大于2分和5分的找零与此类似,那么找零时就有三种选择,即找零后剩余金额为n-1,n-2,n-5,这三种选择总的找零数最少的方案即为所求解的方案。

显然,最终的找零方案与执行当前选择后剩余的金额的找零相关,即金额n的最优找零方案包含了金额n-1,n-2,n-5的最优找零方案,于是可得如下状态转移方程:

具体的求解过程:

初始化F

(1)=1,F

(2),F(5)=1

F

(1)

1

F

(2)

F(3)

min{F

(2)+1,F

(1)+1}=2

F(4)

min{F

(2)+1,F(3)+1}=2

F(5)

F(6)

min{F

(1)+1,F(4)+1,F

(1)+1}=2

F(n)

min{F(n-1)+1,F(n-2)+1,F(n-5)+1}

算法设计思路及求解过程

思路:

题目所描述的整个过程是“并行的”,而且所有人到达各自楼层的用时只与最晚到达的人有关。

由于去各个楼层的具体数目对结果没有影响,所以可以将“电梯还剩i个人”表述成“电梯里面的乘客还要去i个楼层”。

电梯从第1层开始向上运行,任意时刻的状态都可以由“电梯当前所处楼层”和“电梯里面都有哪些乘客确定”,初始状态为“电梯在1楼”和“所有乘客都在电梯上”。

在电梯运行的每一个阶段都需要作出相应的决策,哪些乘客乘坐电梯到目的层,哪些乘客选择爬楼梯到达目的地。

决策后,电梯里面的乘客被分成两部分:

乘客留在电梯里面继续上升;

乘客离开电梯走楼梯到达。

求当前状态下电梯里面的乘客所有人到达目的所需要的最短时间,只需要找到一个最优决策,使得下电梯的乘客和留在电梯中的乘客最晚到达时间越短越好,这个最短时间就是当前状态下的最优解。

如果假设决策后留在电梯里面的乘客到达各自楼层所需要的时间为T1,离开电梯的各自到达目的地所需时间为T2,则min{max(T1,T2)}就是当前状态的最优解,其中T1可以由“当前层数+1”和“决策后剩下的人”确定的状态得到;

T2则为下电梯走楼梯到达目的走楼梯最多的那一位乘客所花时间。

如果去第k层的乘客选择在当前楼层下电梯,那么第1,2…k-1层的乘客也应该选择在此时下电梯(如图1所示),这样就可以得到当前决策下的一个最优解。

为了进一步处理停靠请求,对楼层按从高到低进行排序,并以此进行编号,如此可以避免在求解过层中处理不连续的请求,如:

图1解题结论

4,5,10。

使用i,j两个参数表示电梯当前的状态,即电梯在第i层,电梯中有j位乘客。

综上所述,可得如下状态转移方程:

f(i,j)表示电梯在第i层楼时,电梯中j个人都到达目的地所需要的最短时间。

具体求解过程:

第一步:

计算初始状态f(topFloor,1),f(topFloor,2),…,f(topFloor,n);

第二步:

根据状态转移方程计算f(i,j);

第三步:

根据计算最优值时记录的信息求解最优解。

1.3算法程序流程

图2Input函数流程图

图3solve函数流程图

图4main函数流程图

图5calculate函数流程图

图6tStay函数流程图

图7tLeave函数流程图

1.4算法的程序实现代码

#include<

iostream>

cstring>

algorithm>

#include<

cmath>

limits>

vector>

usingnamespacestd;

constintmaxN=30,maxF=31;

//电梯上一层楼所需时间,电梯每次停靠时长,人走一层楼所需时间

constintve=4,st=10,vw=20;

intn,f[maxN+1];

//数据读取

boolinput(){

cin>

>

n;

if(n==0)returnfalse;

//注意:

f[1...n]中楼层数从高到低排列

for(inti=n;

i>

=1;

i--)

f[i];

returntrue;

}

intdp[maxF+1][maxN+1],nextJ[maxF+1][maxN+1];

//目前电梯在第currF层,第L层到第R层乘客离开电梯

//函数返回这些离开电梯的乘客中最晚到达目的层所需时间

inttLeave(intcurrF,intl,intr){

if(l>

r)return0;

//仅需考虑两端,无论此刻电梯在何处,第l-r层花时间最多的

//一定是离电梯当前所在楼层最远的乘客

returnmax(abs(currF-f[l]),abs(currF-f[r]))*vw;

//现在电梯在第i层,电梯里面本来有j位乘客,离开电梯的乘客剩下jj位

inttStay(inti,intj,intjj){

//没有乘客离开,电梯不停

if(j==jj||i==1)

returndp[i+1][jj]+ve;

//所有人都离开电梯

elseif(jj==0)

return0;

//一般情况,电梯在第i层停靠

else

returndp[i+1][jj]+ve+st;

//

voidcalculate(){

//边界:

电梯在顶楼时所有人都必须下电梯

inttopFloor=f[1];

for(intj=1;

j<

=n;

j++){

//1,j表示停靠请求的编号,编号越小表示编号停靠楼层越高

dp[topFloor][j]=tLeave(topFloor,1,j);

}

for(inti=topFloor-1;

i--){

//i表示电梯此刻所在位置

dp[i][j]=numeric_limits<

int>

:

max();

for(intjj=0;

jj<

=j;

jj++){

//计算离开电梯的人和留在电梯里面的人中到达目的地最晚的

inttmp=max(tStay(i,j,jj),tLeave(i,jj+1,j));

//在此求解花费时间最短的乘客

if(dp[i][j]>

tmp){

dp[i][j]=tmp;

//jj以前的乘客均离开电梯

nextJ[i][j]=jj;

cout<

<

dp[1][n]<

endl;

//重构最优解

voidrebuildSolution(){

vector<

stops;

intj=nextJ[1][n],topFloor=f[1];

for(inti=2;

i<

=topFloor;

i++){

if(nextJ[i][j]!

=j){

stops.push_back(i);

j=nextJ[i][j];

if(j==0)break;

stops.size();

for(inti=0;

"

"

stops[i];

voidsolve(){

memset(dp,0,sizeof(dp));

memset(nextJ,0,sizeof(nextJ));

calculate();

rebuildSolution();

题目2切割木材

2.1题目描述

一个木匠从木材公司买了一批木材,每块木材的长度均相同,但由于制作家具时所需的木块长度各不相同,因此需要把这些木材切割成长度不同的木块。

同时每次切割时由于锯子本身有一定的宽度,因此每切割一次就会浪费掉一些木料。

请设计一个程序使木匠能够用最少的木材切割出所需的木块。

输入描述:

输入有若干个测试样例,每个测试样例占一行。

每行由若干个整数构成,第一个整数为所购买的木块的长度L(0<

L<

=30000),第二个整数为锯子的宽度W(0<

W<

=1000),其后的若干个整数分别表示制作家具时需要的木块的长度。

输出描述:

每个测试样例输出一行,为一个整数N,表示制作家具时需要购买的木块的数量。

样例输入:

10001002502505006501000

100050200250250500650970

样例输出:

3

4

2.2算法文字描述

此题目是装载问题的一个变种,与装载问题不同的是此问题没有给出“船”数量,但是给出了船的载重量,因此仍旧可以借鉴解装载问题的思路,即让每一根原材料可以切出更多符合要求的木料,类似于装载问题中“将第一艘轮船尽可能地装满”,即保证切割以后剩余的原材料是最少的。

算法具体描述如下:

Step1:

声明求解结果变量res=0,剩余未切割木料数量count=n,当前已切割木料长度和cw=0,目前最大切割长度bestW=0,求解标记数组visited[n],当前最优求解数组nVisited[n],问题求解状态记录数组res_arr[n],锯口宽度sw;

Step2:

当剩余未切割木料数量count大于0时,利用回溯法进行最大子集和求解。

当i<

n-1时,搜索左子树的条件:

当前节点未被访问且cw+data[i]<

=w+sw,访问左子树时第i层相应节点时将相应访问标记visited[i]置为true,递归搜索该节点的左子树;

递归搜索右子树时,将当前节点访问标记visited[i]置为false;

Step3:

当i>

n-1时,获得一种切割方案,若此次求解结果优于已得求解结果,即bestW<

cw,使用nVisited数组记录当前求解状态,同时更新bestW的值;

Step4:

利用回溯法完成1次木料切割后,更当前问题求解状态res_arr数组,根据最新的求解状态更新未切割木料数量count,同时res++,若count=0则求解结束,否则重复2,3,4直至count=0。

2.3算法程序流程

图8main函数流程图

图9input函数流程图

图10solve函数流程图

图11backtrack函数流程图

2.4算法的程序实现代码

stdio.h>

malloc.h>

#defineMAX_SAMPLE_LENGTH50

/*回溯法求解*/

int*in=(int*)malloc(MAX_SAMPLE_LENGTH*sizeof(int));

int*data=(int*)malloc(MAX_SAMPLE_LENGTH*sizeof(int));

bool*visited=(bool*)malloc(MAX_SAMPLE_LENGTH*sizeof(bool));

bool*nVisited=(bool*)malloc(MAX_SAMPLE_LENGTH*sizeof(bool));

bool*res_arr=(bool*)malloc(MAX_SAMPLE_LENGTH*sizeof(bool));

intw;

//原材料长度

intn;

//数据元素个数

intsw;

//锯口宽度

intcw;

//当前已锯木头长度和

intres;

//求解结果

intbestW;

//当前求解最大值

boolflag=true;

//初始化数据保存数组

memset(in,0,MAX_SAMPLE_LENGTH*sizeof(int));

memset(visited,false,MAX_SAMPLE_LENGTH*sizeof(bool));

memset(res_arr,false,MAX_SAMPLE_LENGTH*sizeof(bool));

memset(nVisited,false,MAX_SAMPLE_LENGTH*sizeof(bool));

//记录输入数据个数

n=0;

//读取数据-原材料(木头)长度

scanf("

%d"

&

w);

if(0==w)flag=false;

sw);

while(flag){

data+n);

n++;

charch=getchar();

if(ch=='

\n'

)break;

returnflag;

voidbacktrack(inti,intk){

if(i>

n-1){

if(bestW<

cw){

//记录最优值

bestW=cw;

//记录当前最优解

nVisited[i]=visited[i];

return;

//进入右子树条件

if(!

res_arr[i]&

&

cw+data[i]+k*sw<

=w){

//记录当前已锯木头数量

k++;

//进入右子树实际操作

cw+=data[i];

//访问标记

visited[i]=true;

backtrack(i+1,k);

cw-=data[i];

k--;

visited[i]=false;

intsolve(int*data,intn){

res=0;

//求解结果初始化

intcount=n;

while(count>

0){

//初始化,cw当前已锯木头长度和,

//count剩余未锯木头数量,bestW本次求解最大长度和

cw=0,count=0,bestW=0;

backtrack(0,0);

//更新待解决问题状态

res_arr[i])

res_arr[i]=nVisited[i];

//剩余未求解元素个数

res_arr[i])count++;

//记录求解结果

res++;

returnres;

intmain(){

while(input()){

solve(data,n);

printf("

\n%d\n"

res);

题目3设计题

3.1题目描述

给定一个数塔,如图12所示。

在此数塔中,从顶部出发,在每一节点可以选择向左走还是向右走,一直走到底层。

请找出一条路径,使路径上的数值和最大。

图12数塔

3.2输入要求

第一行输入一个整数n,n表示数塔的层数,第2,…,n+1行为数塔对应节点的数值。

3.3输出要求

第一行输出路径数值和,第二行输出具体路径。

3.4样例输入

5

13

1112

40716

614158

127132411

3.5样例输出

91

(1,1)->

(2,1)->

(3,1)->

(4,2)->

(5,3)

3.6测试样例输入

7

11

98

12107

4152319

178211216

322524283127

85910111315

3.7测试样例输出

113

(3,2)->

(4,3)->

(5,3)->

(6,4)->

(7,5)

3.8算法实现的文字描述

动态规划采用自底向上逐层分阶段决策

1)第1次决策,针对第4层

如果最优路径经过6,则从第4层到第5层应该经过12,则第4+第5层的最大路径为6+12=18

如果最优路径经过14,则从第4层到第5层应该经过13,则第4+第5层的最大路径为13+14=27

……

这样实际上将5阶数塔变为4阶数塔问题了。

2)逐层向上递推,最后得到问题的最优解

根据题意,待处理的数据规模同数塔的层数有关,同时数据节点的个数与层数相同,所以可以使用二维数组data存储待处理节点数值,只有一半的节点有数值,实际上是一个下三角矩阵。

可以较为容易地得到问题状态转移方程:

声明变量数塔层数n,待处理数据节点数值数组data[n][n],结果(状态)数组d[n][n];

输入数塔层数n,维数组data和d分配存空间;

初始化第n层结果(状态)数组值;

根据状态转移方程求解d(i,j),其中i从n-1到1,j从1到i;

Step5:

输出d(1,1);

Step6:

根据数组d求解具体路径并输出。

3.9算法程序流程

图13main函数流程图

图14tower_walk函数流程图

3.10算法的程序实现代码

math.h>

int*data=NULL;

//存储数塔原始数据

int*dp=NULL;

//状态值记录

//塔的层数

/*动态规划实现数塔求解*/

voidtower_walk()

{

intindex1=0,index2=0;

//dp初始化

for(inti=0;

i<

n;

++i)

{

index1=(n-1)*n+i;

dp[index1]=data[index1];

inttemp_max;

for(inti=n-2;

i>

=0;

--i)

for(intj=0;

j<

=i;

++j)

//使用递推公式计算dp的值

index1=(i+1)*n+j;

index2=i*n+j;

temp_max=(dp[index1]>

dp[index1+1])?

dp[index1]:

dp[index1+1];

dp[index2]=temp_max+data[index2];

/*打印最终结果*/

voidprint_result()

intindex=0;

%d\n"

dp[index]);

intnode_value;

//首先输出塔顶元素

intj=0,i=0;

(%d,%d)"

i+1,j+1);

for(i=1;

index=(i-1)*n+j;

node_value=dp[index]-data[index];

//如果node_value==dp[i][j]则说明下一步应该是data[i][j];

//如果node_value==dp[i][j+1]则说明下一步应该是data[i][j+1].

index=i*n+j+1;

if(node_value==dp[index])++j;

->

\n"

);

intmain()

n);

data=(int*)malloc(n*n*sizeof(int));

memset(data,0,n*n*sizeof(int));

dp=(int*)malloc(n*n*sizeof(int));

memset(dp,0,n*n*sizeof(int));

index=i*n+j;

data+index);

tower_walk();

print_result();

算法分析与设计课程总结

通过本课程各个专题模块的学习,回顾和巩固了曾经学习过的知识,并且有了新的感受和收获。

老师的教学具有很强的启发性,在整个学习过程中,通过具体的示例详细地讲解了穷举法、动态规划、贪心算法、回溯法和分支限界法等

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 职业教育 > 中职中专

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1