最短路径拯救007 的设计.docx
- 文档编号:24648987
- 上传时间:2023-05-29
- 格式:DOCX
- 页数:26
- 大小:176.66KB
最短路径拯救007 的设计.docx
《最短路径拯救007 的设计.docx》由会员分享,可在线阅读,更多相关《最短路径拯救007 的设计.docx(26页珍藏版)》请在冰豆网上搜索。
最短路径拯救007的设计
数据结构课程设计报告
最短路径:
拯救007的设计
最短路径:
拯救007的设计
1设计内容
1)设计题目
看过007系列电影的人们一定很熟悉James Bond这个世界上最著名的特工了。
在电影“Live and Let Die”中James Bond被一组毒品贩子抓住并且关到湖中心的一个小岛上,而湖中有很多凶猛的鳄鱼。
这时James Bond做出了最惊心动魄的事情来逃脱——他跳到了最近的鳄鱼的头上,在鳄鱼还没有反应过来的时候,他又跳到了另一只鳄鱼的头上„„最后他终于安全地跳到了湖岸上。
假设湖是100×100的正方形,设湖的中心在(0,0),湖的东北角的坐标是(50,50)。
湖中心的圆形小岛的圆心在(0,0),直径是15。
一些凶猛的鳄鱼分布在湖中不同的位置。
现已知湖中鳄鱼的位置(坐标)和James Bond可以跳的最大距离,请你告诉James Bond一条最短的到达湖边的路径。
他逃出去的路径的长度等于他跳的次数。
2)输入要求
程序从“input.txt”文件中读取输入信息,这个文件包含了多组输入数据。
每组输入数据的起始行中包含两个整数n和d,n是鳄鱼的数量而且n≤100,d是007可以跳的最大距离而且d>0。
起始行下面的每一行是鳄鱼的坐标(x,y),其中x, y都是整数,而且没有任何两只鳄鱼出现在同一个位置。
input.txt文件以一个负数结尾。
3)输出要求
程序输出结果输出到output.txt文件中。
对于每组输入数据,如果007可以逃脱,则输出到output.txt文件的内容格式如下:
第一行是007必须跳的最小的步数,然后下面按照跳出顺序记录跳出路径上的鳄鱼坐标(x,y),每行一个坐标。
如果007不可能跳出去,则将-1写入文件。
如果这里有很多个最短的路径,只需输出其中的任意一种
2设计分析
1.明确题目中的已知条件
(1)007被关的小岛在湖的中心;
(2)小岛是圆形,圆心在(0,0),而且直径是15; (3)没有两只鳄鱼在同一个位置; (4)鳄鱼的坐标值都是整数。
2.一些判断007是否能跳出的细节
(1)判断007是否能够直接从岛上跳到湖岸:
由已知条件可得,湖是一个正方形,边长为100,中心是在(0,0),四个顶点分别是(50,50),(50,-50),(-50,-50),(-50,50)。
而湖中小岛的直径是15.所以如果007可以跳大于等于(50-15/2)=42.5,他就可以直接从小岛跳到湖岸,而不用经过鳄鱼。
(2)判断007是否能够直接从岛上跳到湖中点A:
已知半径是7.5,假设点A的坐标是(x,y),007的步长是L,则当点A到中心(0,0)的距离小于等于007的步长加上小岛的半径7.5的时候就能确定007可以从岛上跳到点A,即:
x*x+y*y<=(L+7.5)*(L+7.5)。
(3)判断007是否能够从点A跳到点B:
假设007的步长是L所以如果两点之间的距离小于等于L,则判断007可以从A跳到B,即(A.x-B.x)^2+(A.y-B.y)^2<=L*L;其他情况时007不能从A点跳到B点。
(4)判断007是否能够从点A跳到湖岸:
当从A点到湖岸的距离小于等于007的步长的时候,说明他可以从A点跳到湖岸,|A.x|+L>=50或|A.y|+L>=50;其他情况时007不能从A点跳到湖岸。
2.1主要数据结构与算法的设计
为了记录007跳过的路径,可定义如下结构:
typedefunsignedintVertex;
typedefdoubleDistance;
typeedefstructGtrapNodeRecord{
intX;/*X轴坐标*/
intY;/*Y轴坐标*/
unsignedintStep;/*记录到本节点一共跳了多少步*/
VertexPath;/*指向本节点的父节点,即跳到本节点之前007所在的节点*/
}GrephNode;
typedefGraphNode*Graph;
2.2寻找跳出路径算法的设计
/*读入一组测试数据返回007跳过的路径Graph,*Bank记录最短到达湖岸的路径。
该算法实际上是应用队列对图进行广度搜索,以寻找到岸边的最短路径(最少的边数)其中入队列与出队列函数分别是Inject()和Pop()*/
Graphread_case(FILE*InFile,intnum,Vertex*Bank,DequeD)
{
GraphG=NULL;
DistanceJamesJump;
VertexV;
intx,y;
inti,Times;
*Bank=0;
fscanf(InFile,"%lf",&JamesJump);
if(CheckForEnd(0,0,JamesJump+ISLAND_DIAMETER/2.0))
{
for(i=0;i<(num<<1);i++)/*一步便跳出的情况*/
fscanf(InFile,"%d",&x);
*Bank=1;
}
elseif(num>0)/*007必须经过鳄鱼头上的情况*/
{
num+=2;
G=GraphNew(num);
for(i=2;i { fscanf(InFile,"%d",&x); fscanf(InFile,"%d",&y); G[i].X=x; G[i].Y=y; if(CheckForStart(x,y,JamesJump))/*判断是否能跳上该点*/ { G[i].Path=1;/*007可以跳到*/ G[i].Step=1;/*一步*/ if(CheckForEnd(x,y,JamesJump))/*判断该点是否能跳出*/ { *Bank=i;/*007可以跳出*/ Times=(num-i-1)<<1; for(i=0;i fscanf(InFile,"%d",&y); DequeClear(D); break; } else Inject(i,D);/*插入该点,并开始下一个检测*/ } } while(! IsEmpty(D))/*只经过一个鳄鱼无法跳出,必须还要跳到其它鳄鱼的情况*/ { V=Pop(D); for(i=2;i { if((G[i].Step>G[V].Step+1) &&CheckForConnect(G,V,i,JamesJump)) { G[i].Path=V; G[i].Step=G[V].Step+1; if((G[i].Step &&CheckForEnd(G[i].X,G[i].Y,JamesJump)) *Bank=i; else Inject(i,D); } } } } returnG; } 在执行完算法read_case后,*Bank值可能如下3种可能: (1)0,意味着007无法逃脱出去; (2)1,意味着007可以直接从岛上跳出去,而不用经过鳄鱼的脑袋; (3)k,返回的第k点是007经过最短路径逃出鳄鱼潭是经过的最后一个顶点。 可以根据G[k]的path参数来追踪该点的上一点,由此类推可以得到007逃脱的最短路径。 3设计实践 4测试方法 •007步长很大,以至于可以直接跳出,例如: 043 -1 •007不可能逃出去的情况(根本就没有鳄鱼),例如: 01 -1 •一般情况的例子,例如: 4 10 17 0 27 0 37 0 45 0 10 20 30 1 •最短路径有多条,只需要输出任意一种即可,例如: 25 10 8 8 最短路径: 拯救007 2510 88 99 10 10 11 11 12 12 13 13 14 14 15 15 16 16 18 18 20 20 23 23 25 25 27 27 28 28 29 29 31 31 33 33 35 35 38 38 41 41 44 44 46 46 47 47 49 49 输出结果: 7 9 9 16 16 23 23 28 28 35 35 41 41 •input.txt文件中,名称不正确、空文件、缺少部分输入等不规范情况,例如: 5 10 10 10 -25 30 30 30 注: 缺少鳄鱼点(应有5个鳄鱼点)和文件结尾符(-1)。 下面给出一个较复杂的测试用例和期望输出结果。 5程序运行效果 5.1在input输入测试数据,如图1所示: (图1输入测试数据) 5.2在output查看测试结果,如图2所示: (图2输出测试数据) 6设计心得 通过近一周的课程设计,让我深刻认识到断点调试的必要性;同时让我了解到动手的重要性,开始的时候,明明有满脑子的想打合算法,就是很难把想法和算法用代码实现;通过此次课程设计,我的动手能力和算法有了明显的提高。 由于程序是直接输出文件的,没有窗口输出,出错时是无法看出哪里有错,所以我一次输出文件中的数据,观察数据变化,找错并改错,这是一个非常有效的改错方法。 7参考文献 【1】《数据结构课程设计》 何钦铭 冯雁 陈越 著 浙江大学出版社 2015-2 【2】《数据结构(C语言版)》 严蔚敏 吴伟民 著 清华大学出版社 2011-11 8附录 Deque.c #include"Deque.h" #include"error.h" #include /******创建新的Deque******/ DequeDequeNew() { DequeD; D=malloc(sizeof(structDequeRecord)); CHECK(D); D->Front=D->Rear=malloc(sizeof(structNodeRecord));/*空的头*/ CHECK(D->Front); D->Front->Element=0;/*初始化*/ D->Rear->Next=NULL; returnD; } /******删除Deque******/ voidDequeDelete(DequeD) { if(D) { while(D->Front) { D->Rear=D->Front->Next; free(D->Front); D->Front=D->Rear; } free(D); } } /******DequeClear删除所有的节点除了头节点******/ voidDequeClear(DequeD) { if(D) { while(D->Front->Next)/*删除第一个节点*/ { D->Rear=D->Front->Next->Next; free(D->Front->Next); D->Front->Next=D->Rear; } D->Rear=D->Front; } } /******判断Deque是否为空******/ intIsEmpty(DequeD) { returnD->Front==D->Rear; } /******将X元素压占到D中******/ voidPush(ElemTypeX,DequeD) { NodeNewNode; NewNode=malloc(sizeof(structNodeRecord));/*建立新的节点*/ CHECK(NewNode); NewNode->Element=X; NewNode->Next=D->Front->Next; if(D->Front==D->Rear)/*如果D为空*/ D->Rear=NewNode; D->Front->Next=NewNode;/*压栈*/ } /******将第一个元素出栈******/ ElemTypePop(DequeD) { NodeTemp; ElemTypeItem; if(D->Front==D->Rear) { Error("Dequeisempty"); return0; } else { Temp=D->Front->Next;/*得到第一个元素*/ D->Front->Next=Temp->Next;/*重置第一个元素*/ if(Temp==D->Rear)/*如果只有一个元素*/ D->Rear=D->Front;/*将D置空*/ Item=Temp->Element; free(Temp); returnItem; } } /******插入元素X至D末尾******/ voidInject(ElemTypeX,DequeD) { NodeNewNode; NewNode=malloc(sizeof(structNodeRecord));/*创建新节点*/ CHECK(NewNode); NewNode->Element=X; NewNode->Next=NULL; D->Rear->Next=NewNode; D->Rear=NewNode; } Deque.h typedefunsignedintElemType;/*在本程序中ElemType指定为int*/ /*链表形式*/ typedefstructNodeRecord{ ElemTypeElement; structNodeRecord*Next;/*指向下一个node*/ }*Node; typedefstructDequeRecord{ NodeFront,Rear;/*分别指向Deque的前后两个点*/ }*Deque; DequeDequeNew(); voidDequeDelete(DequeD); voidDequeClear(DequeD); intIsEmpty(DequeD); voidPush(ElemTypeX,DequeD); ElemTypePop(DequeD); voidInject(ElemTypeX,DequeD); #include"error.h" #include #include erroe.c /******打印错误信息,并退出程序******/ voidError(constchar*msg) { if(NULL! =msg) fprintf(stderr,"%s\n",msg); exit(-1); } /******打印警告信息,但并不退出程序******/ voidWarning(constchar*msg) { if(NULL! =msg) fprintf(stderr,"%s\n",msg); } erroe.h #defineCHECK(X)if(NULL==(X))Error("Outofspace") voidError(constchar*msg); voidWarning(constchar*msg); #include"Graph.h" #include"error.h" #include Graph.c /******创建新的Graph******/ GraphGraphNew(intNodeNum) { GraphG; inti; if(NodeNum<=0)returnNULL; G=malloc(NodeNum*sizeof(GraphNode));/*分配空间*/ CHECK(G); for(i=0;i { G[i].X=0; G[i].Y=0; G[i].Step=INFINITY; G[i].Path=0; } returnG; } /******删除一个Graph)******/ voidGraphDelete(GraphG) { if(G)free(G); } /*******判断007是否能从起始处跳至该点(x,y),步长是d******/ intCheckForStart(intx,inty,Distanced) { doublet; t=(ISLAND_DIAMETER+(d*2.0)); return(x*x+y*y)<=t*t/4.0; /*x^2+y^2<=(ISLAND_DIAMETER/2.0+d)^2*/ } /*******判断007是否能从该点跳至河岸,步长是d******/ intCheckForEnd(intx,inty,Distanced) { if(x<0)x=-x;/*取x的绝对值*/ if(y<0)y=-y;/*取y的绝对值*/ return(d>=LAKE_BOUNDARY_X-x)/*由于湖是个正方形,只需检查这两个距离*/ ||(d>=LAKE_BOUNDARY_Y-y); } /*******判断007是否能从点i跳至点j,步长是d******/ intCheckForConnect(Graphg,Vertexi,Vertexj,Distanced) { intx,y; x=g[i].X-g[j].X; y=g[i].Y-g[j].Y; returnx*x+y*y<=d*d; } Graph.h #defineISLAND_DIAMETER15/*小岛的直径*/ #defineLAKE_BOUNDARY_X50/*小岛到湖边的距离,在x轴上*/ #defineLAKE_BOUNDARY_Y50/*小岛到湖边的距离,在y轴上*/ #defineINFINITY10000/*可以跳的步数的最大值*/ typedefunsignedintVertex; typedefdoubleDistance; typedefstructGraphNodeRecord{ intX;/*x轴坐标*/ intY;/*y轴坐标*/ unsignedintStep;/*跳至该点的步数*/ VertexPath;/*记录上一个点*/ }GraphNode; typedefGraphNode*Graph; GraphGraphNew(intNodeNum); voidGraphDelete(GraphG); /*判断007是否能从起始处跳至该点(x,y)*/ intCheckForStart(intx,inty,Distanced); /*判断007是否能从该点跳至河岸*/ intCheckForEnd(intx,inty,Distanced); /*判断007是否能从点i跳至点j*/ intCheckForConnect(Graphg,Vertexi,Vertexj,Distanced); main.c #include"Graph.h" #include"Deque.h" #include"error.h" #include #include /******读入一个case返回一个Graph,*Bank记录最短到达河岸的路径******/ Graphread_case(FILE*InFile,intnum,Vertex*Bank,DequeD) { GraphG=NULL; DistanceJamesJump; VertexV; intx,y; inti,Times; *Bank=0; fscanf(InFile,"%lf",&JamesJump); if(CheckForEnd(0,0,JamesJump+ISLAND_DIAMETER/2.0)) { for(i=0;i<(num<<1);i++)/*一步便跳出的情况*/ fscanf(InFile,"%d",&x); *Bank=1; } elseif(num>0)/*007必须经过鳄鱼头上的情况*/ { num+=2; G=GraphNew(num); for(i=2;i { fscanf(InFile,"%d",&x); fscanf(InFile,"%d",&y); G[i].X=x; G[i].Y=y; if(CheckForStart(x,y,JamesJump))/*判断是否能跳上该点*/ { G[i].Path=1;/*007可以跳到*/
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 最短路径拯救007 的设计 路径 拯救 007 设计
![提示](https://static.bdocx.com/images/bang_tan.gif)