西电人工智能大作业
西电智能大作业

班级学号智能传感技术大作业题目显微成像系统学院电子工程学院专业智能科学与技术学生姓名导师姓名显微镜成像系统一、简介显微镜成像系统以非摄影方式获取微观世界的影像,并可以对获取的图片进行图像分析的系统。
通过逐点、逐行、逐面快速扫描成像,并通过数据线连接到计算机上进行图像分析。
由显微镜摄像头+图像分析软件组合而成的系统,一般被称为显微影像软件、显微镜照相系统、显微摄像系统等。
一般购买显微镜摄像头时都会带有图像分析软件,所以人们很容易和混绕,误以为显微镜成像系统等于显微镜摄像头。
二、系统分类1.基础图象测量软件基本的图象捕获,增强及简[1]单的测量工具2.通用分析图象处理软件应用于科学/工业的图象分析,可以提出证明实验数据3.特定功能的图象分析软件解决相关领域特殊的图象分析要求三、类别纲目1、可见光显微镜1)、按照明技术分①、明视野显微镜②、暗视野显微镜③、荧光显微镜2)、按像的类型分①、相差显微镜②、干涉相差显微镜③、偏光显微镜3)、按镜体结构分①、倒置显微镜②、实体显微镜③、比较显微镜4)、按应用范围分①、教学显微镜②、研究显微镜③、大型万能显微镜2、不可见光显微镜1)、紫外光显微镜2)、红外光显微镜3)、X射线显微镜四、显微成像系统的发展历史公元前一世纪人们就已发现通过球形透明物体去观察微小物体时可以使其放大成像。
1590年,荷兰和意大利的眼镜制造者已经造出类似显微镜的放大仪器。
1610年前后,意大利的伽利略和德国的开普勒在研究望远镜的同时,改变物镜和目镜之间的距离,得出合理的显微镜光路结构,当时的光学工匠遂纷纷从事显微镜的制造、推广和改进。
17世纪中叶,英国的胡克和荷兰的列文胡克,都对显微镜的发展作出了卓越的贡献。
1665年前后,胡克在显微镜中加入粗动和微动调焦机构、照明系统和承载标本片的工作台。
这些部件经过不断改进,成为现代显微镜的基本组成部分。
1673~1677年期间,列文胡克制成单组元放大镜式的高倍显微镜,其中九台保存至今。
人工智能课程大作业

作业题目摘要:机器博弈是人工智能的一个重要研究分支,本文通过设计一个五子棋智能博奕程序,采用传统的博弈树算法,利用剪枝和极大极小树搜索最佳位置,从而实现人机智能博弈。
并对现有算法存在的问题进行探究改进,最后给出展示,结果表明效果比较理想。
关键词:人工智能;五子棋;博弈本组成员:本人分工:α-β剪枝实现1 引言人工智能[1]是一门综合新型的新兴边缘科学,与生物工程、空间技术并列为三大尖端技术,而机器博弈却是其一个重要的研究分支。
它研究如何利用计算机去实现那些过去只能靠人的智力去完成的工作,博弈为人工智能提供了一个很好的应用场所。
博弈过程可以采用与或树进行知识表达,这种表达形式称为博弈树。
α—β剪枝技术是博弈树搜索中最常采用的策略。
2 算法原理与系统设计根据五子棋游戏规则,此次五子棋游戏我们采用基于极大极小值分析法的α—β剪枝算法来实现计算机走棋。
α—β剪枝技术是博弈树搜索中最常采用的策略,α—β剪枝搜索由极大极小值分析法演变而来[2]。
极大极小分析法其基本思想或算法是:(1) 设博弈的双方中一方为MAX,另一方为MIN。
然后为其中的一方(例如MAX)寻找一个最优行动方案。
(2) 为了找到当前的最优行动方案,需要对各个可能的方案所产生的后果进行比较,具体地说,就是要考虑每一方案实施后对方可能采取的所有行动,并计算可能的得分。
(3) 为计算得分,需要根据问题的特性信息定义一个估价函数,用来估算当前博弈树端节点的得分。
此时估算出来的得分称为静态估值。
(4) 当端节点的估值计算出来后,再推算出父节点的得分,推算的方法是:对“或”节点,选其子节点中一个最大的得分作为父节点的得分,这是为了使自己在可供选择的方案中选一个对自己最有利的方案;对“与”节点,选其子节点中一个最小的得分作为父节点的得分,这是为了立足于最坏的情况。
这样计算出的父节点的得分称为倒推值。
(5) 如果一个行动方案能获得较大的倒推值,则它就是当前最好的行动方案。
西安电子科技大学人工智能复习课习题

1.请选用框架法和语义网络法表示下述报道的沙尘暴灾害事件。
(虚拟新华社3月16日电)昨日,沙尘暴袭击韩国汉城,气场与高速公路被迫关闭,造成的损失不详。
此次沙尘暴起因中韩专家认为是由于中国内蒙古地区过分垦牧破坏植被所致。
(提示:分析概况用下划线标出的要点,经过概念化形成槽或节点)2. 请用归结反演的方法求解下述问题。
已知:(1)John 是贼。
(2)Paul 喜欢酒(wine )。
(3)Paul 也喜欢奶酪(cheese )。
(4)如果Paul 喜欢某物,那么John 也喜欢某物。
(5)如果某人是贼,而且他喜欢某物,那么他就会偷窃该物。
请回答下面的问题:John 会偷窃什么?3. MYCIN 是一个用于细菌感染性疾病诊断的专家系统,它的不确定性推理模型中采用可信度作为不确定性量度。
请简述什么是不确定性推理及不确定性推理几个关键问题,并按照MYCIN 系统的推理方法计算结论B1和B2的可信度。
已知初始证据A1,A2,A3的可信度值均为1,推理规则如下:R1: IFA1 THEN B1 (0.8) R2: IFA2 THEN B1 (0.5) R3: IF A3∧B1 THENB2 (0.8) 求CF(B1)和CF(B2)的值。
()()()(),()0,()0121212()()()()(),()0,()012121212()()12,()()0121min{|()|,|()|}12CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H CF H ⎧⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎩+-⨯≥≥=++⨯<<+⨯<- 4.设A 、B 分别是论域U 、V 上的模糊集,U=V={1,2,3,4,5}, A=1/1+ 0.5/2, B=0.4/3+0.6/4+1/5并设模糊知识及模糊证据分别为:IF x is A THEN y is B x is A ’其中,A ’的模糊集为:A ’=1/1+ 0.4/2+ 0.2/3假设A 和A ’可以匹配,请利用模糊推理的方法求出该模糊知识和模糊证据能得出什么样的模糊结论。
大工20秋《人工智能》大作业题目及要求精选全文

可编辑修改精选全文完整版学习中心:专业:年级:年春/秋季学号:学生:完整答案下载后可见题目:深度优先搜索算法1.谈谈你对本课程学习过程中的心得体会与建议?通过这学期的学习,我对人工智能有了一定的感性认识,个人觉得人工智能是一门极富挑战性的科学,从事这项工作的人必须懂得计算机知识,心理学和哲学。
人工智能是包括十分广泛的科学,它由不同的领域组成,如机器学习,计算机视觉等等,总的说来,人工智能研究的一个主要目标是使机器能够胜任一些通常需要人类智能才能完成的复杂工作。
人工智能的定义可以分为两部分,即“人工”和“智能”。
“人工”比较好理解,争议性也不大。
有时我们会要考虑什么是人力所能及制造的,或者人自身的智能程度有没有高到可以创造人工智能的地步,等等。
但总的来说,“人工系统”就是通常意义下的人工系统。
关于什么是“智能”,就问题多多了。
这涉及到其它诸如意识、自我、思维等等问题。
人唯一了解的智能是人本身的智能,这是普遍认同的观点。
但是我们对我们自身智能的理解都非常有限,对构成人的智能的必要元素也了解有限,所以就很难定义什么是“人工”制造的“智能”了。
关于人工智能一个大家比较容易接受的定义是这样的:人工智能是人造的智能是计算机科学、逻辑学、认知科学交叉形成的一门科学,简称AI。
人类正向信息化的时代迈进,信息化是当前时代的主旋律。
信息抽象结晶为知识,知识构成智能的基础。
因此,信息化到知识化再到智能化,必将成为人类社会发展的趋势。
人工智能已经并且广泛而有深入的结合到科学技术的各门学科和社会的各个领域中,她的概念,方法和技术正在各行各业广泛渗透。
而在我们的身边,智能化的例子也屡见不鲜。
在军事、工业和医学等领域中人工智能的应用已经显示出了它具有明显的经济效益潜力,和提升人们生活水平的最大便利性和先进性。
2.《人工智能》课程设计,从以下5个题目中任选其一作答。
《人工智能》课程设计题目三:深度优先搜索算法要求:(1)撰写一份word文档,里面包括(算法思路、算法程序框图、主要函数代码)章节。
大工《人工智能》大作业参考题目及要求【内容仅供参考】592

题目:广度优先搜索算法1.谈谈你对本课程学习过程中的心得体会与建议?人工智能是一门前沿且综合性非常强的课程,自己在整个课程的学习中,认识到人工智能领域的许多方面,以及了解和学习了人工智能课程相关的一些课程的学习过程中,涉及到了较多的计算机知识点,包括很多计算机个人建议学完这门课程后,多去尝试做一些简单的实践练习,实践中除了相关理论知识如算法等作为分析支撑,还要能够通过代码来编写实现一些简单案例,并进行测试验证和推导,最后尽可能将实现的案例进行举一反三,学习效果会大大提升。
在尝试实现练习案例中,涉及到编程技术,首先至少应该熟练使用一门编程语言,比较推荐Python作为主要编程语言进行实现案例以及日常练习,而且在Python编程相关的领域内,本身已经有很多相关成熟的代码demo去借鉴参考,这也有助于自己快速的上手和试验。
另外,无论是课程学习中,还是学习完后,一定要善于作笔记总结,汇总遇到的每个难点知识。
现在互联网比早以前发展的更成熟,我们可以通过互联网搜索相关知识,进行课外补充,这也是一种非常有效的提升课程知识的方式。
同时,利用互联网进行沟通探讨也是一种良好的学习方式,比如自己写博客交流,或者在相关论坛进行发帖提问式交流,都是非常方便且有效的,最后不要忘记将知识点进行再次归纳、记录进自己的笔记中。
目前人工智能技术的发展已经进入了更广泛的领域,而且目前还在不断的发展并且欣欣向荣,所以该课程是一门非常有意义的课程,学完这门课程后,个人推荐应该对这个领域进行持续关注,结合现代化人工智能需求,以及融入到身边的日常案例,积极进行更广泛和有深度的自我研究学习。
2.《人工智能》课程设计,从以下5个题目中任选其一作答。
题目:广度优先搜索算法广度优先搜索算法算法介绍:广度优先搜索算法又称为宽度优先搜索算法,英文全称是Breadth First Search(BFS),它是属于一种盲目搜索算法,该算法按照广度或宽度进行扩展搜索的,如果目标节点存在,用该算法总可以找到该目标节点,而且是最短路径节点,但该算法的时间和空间复杂度都相对比较高。
人工智能实验指导书+作业展示

《人工智能技术导论》实验指导书西北工业大学计算机学院目录一实验纲要 (1)二上机要求 (2)三实验内容 (3)实验一图搜索与问题求解 (3)实验1.1 启发式搜索 (3)实验1.2 A*算法搜索 (9)实验1.3 其他应用问题 (12)实验二产生式系统推理 (14)实验三TSP问题的遗传算法实现 (20)四实验报告模板 (27)人工智能实验一实验报告 (27)人工智能实验二实验报告 (28)人工智能实验三实验报告 (29)附件1 TSP问题的遗传算法程序模板 (30)附件2 学生作业作品展示 (35)一实验纲要一实验教学的目的、任务与要求将人工智能基础理论应用于实际问题的解决当中,加深学生对所学知识的理解,提高学生的实际动手能力。
二实验项目内容1图搜索策略实验用启发式搜索方法/A*算法求解重排九宫问题/八数码问题。
2产生式系统的推理以动物识别系统为例,实现基于产生式规则的推理系统。
3 TSP问题的遗传算法实现以N个结点的TSP问题为例,用遗传算法加以求解。
三参考教材人工智能技术导论-第3版,廉师友编著,西安电子科技大学出版社,2007。
四使用主要仪器设备说明在Windows2000/XP上,选用Java/C/C++/Matlab等语言进行实现。
五实验考核实验为12学时,分4次课完成。
每个实验题目在课堂上分别按百分制给出。
其中包括课堂纪律、程序运行结果、课堂回答问题及实验报告成绩等。
实验课总成绩为3个实验题目的平均成绩。
实验课要求学生提前预习,上课时需向辅导老师提交预习报告,报告格式和内容不作过多要求,只需简要说明自己本次实验的大体思想。
预习报告形式不限,电子版或手写版均可。
1 考核方法由各班辅导老师当堂检查源程序和运行结果,并提问相关问题,课堂上给出成绩并记录。
每个题目完成后把源代码和实验报告提交,由辅导老师检查实验报告并给出报告成绩。
2 评分标准每个实验题目根据以下标准进行考核:1)考勤分20分。
西电电院人工智能课程大作业。

西电人工智能大作业八数码难题一.实验目的八数码难题:在3×3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空的,其初始状态如图1所示,要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态到目标状态。
例如:(a) 初始状态 (b) 目标状态图1 八数码问题示意图请任选一种盲目搜索算法(深度优先搜索或宽度优先搜索)或任选一种启发式搜索方法(A 算法或 A* 算法)编程求解八数码问题(初始状态任选),并对实验结果进行分析,得出合理的结论。
本实验选择宽度优先搜索:选择一个起点,以接近起始点的程度依次扩展节点,逐层搜索,再对下一层节点搜索之前,必先搜索完本层节点。
二.实验设备及软件环境Microsoft Visual C++,(简称Visual C++、MSVC、VC++或VC)微软公司的C++开发工具,具有集成开发环境,可提供编辑C语言,C++以及C++/CLI 等编程语言。
三.实验方法算法描述:(1)将起始点放到OPEN表;(2)若OPEN空,无解,失败;否则继续;(3)把第一个点从OPEN移出,放到CLOSE表;(4)拓展节点,若无后继结点,转(2);(5)把n的所有后继结点放到OPEN末端,提供从后继结点回到n的指针;(6)若n任意后继结点是目标节点,成功,输出;否则转(2)。
流程图:代码:#include <stdlib.h>#include <stdio.h>typedef struct Node {int num[9]; //棋盘状态int deepth; //派生的深度 g(n)int diffnum; //不在位的数目 h(n)int value; //耗散值 f(n)=g(n)+h(n)struct Node * pre;struct Node * next;struct Node * parent;}numNode; /* ---------- end of struct numNode ---------- */int origin[9]; //棋盘初始状态int target[9]; //棋盘目标状态int numNode_num,total_step;numNode *open,*close; //Open表和Close表numNode *create_numNode(){return (numNode *)malloc(sizeof(numNode));}numNode *open_getfirst(numNode *head); //返回第一项,并从Open表中删除void open_insert(numNode *head,numNode *item); //向Open表中按序插入新节点void close_append(numNode *head,numNode *item); //向Close表中插入新节点int expand(numNode *item); //扩展节点int print_result(numNode *item); //打印结果numNode *copy_numNode(numNode *orgin);char isNewNode(numNode *open,numNode *close,int num[9]);//是否在Open表或Close表中void print_num(int num[9]); //打印棋盘状态int diff(int num[9]); //求不在位棋子的个数void init(); //初始化,获得棋盘初始状态和目标状态void swap(int *a,int *b);int operate(int num[],int op);void free_list(numNode *head);/** Name: 主函數* Description: 程序入口*/Int main ( int argc, char *argv[] ){//初始化Open表和Close表open=create_numNode();close=create_numNode();open->pre=open->next=close->pre=close->next=NULL; init(); //由用户输入初始和目标状态//初始化初始节点numNode *p1;p1=create_numNode();p1->parent=NULL;p1->deepth=0;int i=0;for ( i=0; i<9; i++){p1->num[i]=origin[i];}open_insert(open,p1);numNode_num=1;p1=open_getfirst(open);while (p1!=NULL){close_append(close,p1);if(expand(p1))return EXIT_SUCCESS;p1=open_getfirst(open);}printf("No solution!\n");return EXIT_SUCCESS;} /* ---------- end of function main ---------- */voidinit ( ){while(1){printf("Please input opriginal status:\nFor example:123456780 stands for\n""1 2 3\n""4 5 6\n""7 8 0\n");char temp[10];scanf("%s",&temp);int i=0;for ( i=0;i<9 && temp[i]-'0'>=0 && temp[i]-'0'<=8; i++){origin[i]=temp[i]-'0';}printf("Please input target status:\n");scanf("%s",&temp);int j=0;for ( j=0; j<9 && temp[j]-'0'>=0 && temp[j]-'0'<=8; j++){target[j]=temp[j]-'0';}system("cls");if ( i==9&&j==9){break;}}} /* ----- end of function init ----- */voidopen_insert (numNode *head,numNode *item){numNode *p,*q;p=head->next;q=head;while ( p!=NULL && item->value > p->value ){q=p;p=p->next;}q->next=item;item->pre=q;item->next=p;if(p!=NULL){p->pre=item;}} /* ----- end of function open_insert ----- */numNode *open_getfirst (numNode *head){numNode *p;if ( head->next == NULL ){return NULL;}p=head->next;head->next=p->next;if ( p->next != NULL ){p->next->pre=head;}p->pre=NULL;p->next=NULL;return p;} /* ----- end of function open_getfirst ----- */voidclose_append (numNode *head,numNode *item){item->next=head->next;item->pre=head;head->next=item;if ( item->next!=NULL ){item->next->pre=item;}} /* ----- end of function close_append ----- */intexpand (numNode *p1){numNode * p2;int op=1;for ( op=1; op<=4; op++){p2=copy_numNode(p1);operate(p2->num,op);if(isNewNode(open,close,p2->num)=='N'){p2->parent=p1;p2->deepth=p1->deepth+1;p2->diffnum=diff(p2->num);p2->value=p2->deepth+p2->diffnum;if(p2->diffnum==0){total_step=print_result(p2);printf("Total step: %d\n",total_step); free_list(open);free_list(close);return 1;}else{numNode_num++;open_insert(open,p2);}}elsefree(p2);}return 0;} /* ----- end of function expand ----- */intoperate(int m[], int op){int blank;blank=0;while (m[blank]!=0 && blank<9 )++blank;if (blank==9)return 1;switch (op) {case 1: /* up */if (blank>2)swap(m+blank,m+blank-3);break;case 2: /* down */if (blank<6)swap(m+blank,m+blank+3);break;case 3: /* left */if (blank!=0 && blank!=3 && blank!=6) swap(m+blank,m+blank-1);break;case 4: /* right */if (blank!=2 && blank!=5 && blank!=8) swap(m+blank,m+blank+1);break;default : return 1;}return 0;}voidswap(int *a, int *b){int c;c=*a;*a=*b;*b=c;}numNode *copy_numNode (numNode *origin){numNode *p;p=create_numNode();p->deepth=origin->deepth;p->diffnum=origin->diffnum;p->value=origin->value;int i;for ( i=0; i<9; i++){(p->num)[i]=(origin->num)[i];}return p;} /* ----- end of function copy_numNode ----- */intdiff (int num[9]){int i,diffnum=0;for(i=0;i<9;i++)if(num[i]!=target[i])diffnum++;return diffnum;} /* ----- end of function diff ----- */charisNewNode (numNode *open,numNode *close,int num[9]) {numNode *p;int i=0;p=open->next;while ( p!=NULL ){for ( i=0; i<9; i++){if(p->num[i]!=num[i])break;}if(i==9)return 'O'; //Openp=p->next;}p=close->next;while ( p!=NULL ){for ( i=0; i<9; i++){if(p->num[i]!=num[i])break;}if(i==9)return 'C'; //Closep=p->next;}return 'N';} /* ----- end of function isNewNode ----- */voidfree_list (numNode *head){numNode *p,*q;p=head->next;while ( p!=NULL ){q=p->next;free(p);p=q;}free(head);} /* ----- end of function free_list ----- */voidprint_num (int num[9]){int i;for ( i=0; i<9; i++){printf("%d\t",num[i]);if((i%3)==2)printf("\n");}} /* ----- end of function print_num ----- */intprint_result ( numNode *item){numNode *p;int step;p=item;if(p!=NULL){step=print_result(p->parent);printf("\nStep %d:\n",step+1);print_num(p->num);return step+1;}else{return -1;}}四.结果:下图实验结果中,一步代表一层的搜索结果中的最优解;八数码难题的宽度优先搜索树:五.实验分析宽度优先搜索属于一种盲目搜索算法,可以系统的展开所有节点,理论上一定能达到搜寻目的。
西电最优化大作业

p0 f x0 , 当 搜 索 到
xk 1
时
,
共
轭
方
向
为
pk 1 f xk 1 k pk , k 0,1,...,n 2 ,此时, pk 1 与 pk A 共轭,用 Apk 右乘上式得
T pk 1 Apk f xk 1 Apk k pk Apk
m 2 理解为拉格朗日乘子法: minT X ; M min f x M min0, g i x i 1
其中
min0, g i x 2
g i 0,i 1 ~ m
当g i x 0,
,
由
T pk 1 Apk 0
得
f x k 1 Ap k k k 0,1,...,n 2 ,若不满足条件,进行下一次迭代。 pT p Ap k
T
1.2.2 问题求解 本程序编程语言为 MATLAB,终止条件为 f x k x0 =[1 1]。 程序代码见附件conjugate.m 1.2.3 计算结果如下:
三、此次实验的收获
经过几个晚上的艰苦奋斗,努力学习,不断调试程序,最终才得以成功运行 程序并得到满意的结果。 有过山重水复疑无路的困境,但最终迎来的还是柳暗花 明又一村的喜悦。通过此次实验,我的收获主要有以下几点: 以前自己在求解函数最优化问题时都是通过求导、画图等方法,而这几个算法都 是通过不断迭代寻找最优解, 相对来说更有利于电脑编程的实现和推广,对函数 本身性质的要求也不是太高。 在最速下降法中, 沿负梯度方向函数值很快的说法容易使我们相信这一定是 最理想的搜索方向, 沿该方向搜索时收敛速度应该很快,然而在算法实现过程中 发现,梯度法的收敛速度并不快(迭代次数为 45 次) ,比其它算法收敛速度都要 慢。而共轭梯度法仅需要利用一阶导数信息,也不再要求精确的直线搜索,进而 克服了最速下降法收敛慢的缺点(迭代次数为 2 次) 。 内点法和外点法的实质都是构造 “惩罚函数” 或者 “围墙函数 (或障碍函数) ” , 将约束函数其转化为非约束函数, 其中外点法在将函数转化为非约束函数后调用 了“牛顿法”来求解,内点法也尝试过用“牛顿法”来求解非约束函数,但由于 障碍函数为倒数形式, 导致了程序在求矩阵逆的时候产生了无穷大的量,函数无 解,所以内点法采用“直接求导”来求解非约束函数。此外,我也尝试了用求极 限的方法来求解最优点,根据手算的步骤,在求得偏导数为 0 的点后,令障碍因 子 mk→0,求得最优解,方法简单,算法易于实现。 这门课在学习过程中多以理论学习为主,如果平时不注重实践,将自己所学 运用到实际中, 就很难会有太大的收获,通过自己的努力用课堂上的算法解决了 实际问题,无疑加深了自己对算法理论的理解。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
人工智能大作业学生:021151**021151**时间:2013年12月4号一.启发式搜索解决八数码问题1.实验目的问题描述:现有一个3*3的棋盘,其中有0-8一共9个数字,0表示空格,其他的数字可以和0交换位置(只能上下左右移动)。
给定一个初始状态和一个目标状态,找出从初始状态到目标状态的最短路径的问题就称为八数码问题。
例如:实验问题为到目标状态:从初始状态:要求编程解决这个问题,给出解决这个问题的搜索树以及从初始节点到目标节点的最短路径。
2.实验设备及软件环境利用计算机编程软件Visual C++ 6.0,用C语言编程解决该问题。
3.实验方法(1).算法描述:①.把初始节点S放到OPEN表中,计算()f S,并把其值与节点S联系起来。
②.如果OPEN表是个空表,则失败退出,无解。
③.从OPEN表中选择一个f值最小的节点。
结果有几个节点合格,当其中有一个为目标节点时,则选择此目标节点,否则就选择其中任一节点作为节点i。
④.把节点i从OPEN表中移出,并把它放入CLOSED的扩展节点表中。
⑤.如果i是目标节点,则成功退出,求得一个解。
⑥.扩展节点i,生成其全部后继节点。
对于i的每一个后继节点j:a.计算()f j。
b.如果j既不在OPEN表中,也不在CLOSED表中,则用估价函数f把它添加入OPEN表。
从j加一指向其父辈节点i的指针,以便一旦找到目标节点时记住一个解答路径。
c.如果j已在OPEN表或CLOSED表上,则比较刚刚对j计算过的f值和前面计算过的该节点在表中的f值。
如果新的f值较小,则I.以此新值取代旧值。
II.从j指向i,而不是指向它的父辈节点。
III.如果节点j在CLOSED表中,则把它移回OPEN表。
⑦转向②,即GO TO ②。
(2).流程图描述:(3).程序源代码:#include <stdio.h>#include<stdlib.h>struct node{int number[3][3];//用二维数组存放8数码int W;//W表示与目标状态相比错放的数码数int Depth;//记录当前节点的深度struct node *parent;//指向父节点的指针struct node *next;//指向链表中下一个节点的指针};int CounterW(int Number[3][3]){//函数说明:计算当前状态与目标状态的W值int i,j;int W=0;int Desnode[3][3]={1,2,3,8,0,4,7,6,5};for(i=0; i<3; i++)for(j=0; j<3; j++)if(Number[i][j] != Desnode[i][j])W++;return W;}void PrintNode(node *A){int i,j;for(i=0; i<3; i++){for(j=0; j<3; j++)printf("%d ",A->number[i][j]);printf("\n");}printf("\n");}int CheckNode(node *open, node *close, int a[3][3]) {//检验该节点状态是否出现过的子程序int CheckFlag=0;int flag1,flag2;node *p=open;node *q=close;while(p != NULL){flag1=0;for(int i=0; i<3; i++){for(int j=0; j<3; j++)if(a[i][j]==p->number[i][j])flag1++;}if(flag1 == 9)break;elsep=p->next;}while(q != NULL){flag2=0;for(int i=0; i<3; i++){for(int j=0; j<3; j++)if(a[i][j] == q->number[i][j])flag2++;}if(flag2 == 9)break;elseq=q->next;}if((flag1==9) || (flag2==9))CheckFlag=1;//如果出现过,置标志位为1return CheckFlag;}struct node *FindNextNode(node *Prenode, node *open, node *close){ //扩展Prenode指向的节点,并将扩展所得结点组成一条单链表int i,j,m,n; //循环变量int temp; //临时替换变量int flag=0;int a[3][3];//临时存放二维数组struct node *p, *q, *head;head=(node *)malloc(sizeof(node));//head指向该链表首结点,并且作为返回值p=head;q=head;head->next=NULL;//初始化for(i=0;i<3;i++)//找到二维数组中0的位置{for(j=0;j<3;j++)if(Prenode->number[i][j]==0){flag=1;break;}if(flag==1)break;}//根据0的位置的不同,对a进行相应的变换for(m=0;m<3;m++)//将Prenode->number赋给afor(n=0;n<3;n++)a[m][n]=Prenode->number[m][n];if(i+1<=2)//情况1,0向下移{temp=a[i][j]; a[i][j]=a[i+1][j]; a[i+1][j]=temp;int CheckNum=CheckNode(open, close, a);if(CheckNum == 0)//若该结点未出现过则执行下面的操作{q=(node *)malloc(sizeof(node));for(m=0;m<3;m++)//将a赋给扩展节点q->numberfor(n=0;n<3;n++)q->number[m][n]=a[m][n];PrintNode(q);q->parent=Prenode;q->Depth=q->parent->Depth+1;//子结点的深度等于其父结点深度加1q->W=CounterW(q->number);q->next=NULL;p->next=q;//扩展节点插入head链表p=p->next;}}for(m=0;m<3;m++)//将Prenode->number重新赋给afor(n=0;n<3;n++)a[m][n]=Prenode->number[m][n];if(i-1>=0)//情况2,0向上移{temp=a[i][j]; a[i][j]=a[i-1][j]; a[i-1][j]=temp;int CheckNum=CheckNode(open, close, a);if(CheckNum == 0)//若该结点未出现过则执行下面的操作{q=(node *)malloc(sizeof(node));for(m=0;m<3;m++)//将a赋给q->numberfor(n=0;n<3;n++)q->number[m][n]=a[m][n];PrintNode(q);q->parent=Prenode;q->Depth=q->parent->Depth+1;q->W=CounterW(q->number);q->next=NULL;p->next=q;p=p->next;}}for(m=0; m<3; m++)for(n=0; n<3; n++)a[m][n]=Prenode->number[m][n];if(j-1>=0)//情况3,0向左移{temp=a[i][j]; a[i][j]=a[i][j-1]; a[i][j-1]=temp;int CheckNum=CheckNode(open, close, a);if(CheckNum == 0)//若该结点未出现过则执行下面的操作{q=(node *)malloc(sizeof(node));for(m=0; m<3; m++)//将a赋给q->numberfor(n=0; n<3; n++)q->number[m][n]=a[m][n];PrintNode(q);q->parent=Prenode;q->Depth=q->parent->Depth+1;q->W=CounterW(q->number);q->next=NULL;p->next=q;p=p->next;}}for(m=0;m<3;m++)for(n=0;n<3;n++)a[m][n]=Prenode->number[m][n];if(j+1<=2)//情况4,0向右移{temp=a[i][j]; a[i][j]=a[i][j+1]; a[i][j+1]=temp;int CheckNum=CheckNode(open, close, a);if(CheckNum == 0)//若该结点未出现过则执行下面的操作{q=(node *)malloc(sizeof(node));for(m=0; m<3; m++)//将a赋给q->numberfor(n=0; n<3; n++)q->number[m][n]=a[m][n];PrintNode(q);q->parent=Prenode;q->Depth=q->parent->Depth+1;q->W=CounterW(q->number);q->next=NULL;p->next=q;p=p->next;}}head=head->next;return head;}node *insert(node *open,node *head){ //将head链表的结点依次插入到open链表相应的位置,//使open表中的结点按从小到大排序。
函数返回open指针node *p,*q;//p、q均指向open表中的结点,p指向q所指的前一个结点int flag=0;if((open==NULL) && (head != NULL))//初始状态,open表为空{ //首先将head表第一个结点直接放入open表中open=head;q=head;head=head->next;q->next=NULL;}if((open != NULL) && (open->next==NULL) &&(head != NULL)) {//open表中只有一个元素q=open;if((head->W + head->Depth) < (open->W + open->Depth))//若后一结点的f值小于首结点,则将它插入到首结点位置{open=head;head=head->next;open->next=q;}else//或者第二个结点的位置{q->next=head;head=head->next;q=q->next;q->next=NULL;}p=open;}while(head!=NULL){q=open;if((head->W + head->Depth) < (open->W + open->Depth)){ //插入到表头open=head;head=head->next;open->next=q;continue;}else{q=q->next; p=open;} //否则,q指像第二个结点,p指向q前一个结点while(q->next!=NULL) //将head的一个结点插入到链表中(非表尾的位置){if(q->W < head->W){q=q->next;p=p->next;}else{p->next=head;head=head->next;p->next->next=q;break;}}if(q->next==NULL)//将head的一个结点插入到表尾或倒数第二个位置{if((q->W + q->Depth) < (head->W + head->Depth)){q->next=head;head=head->next;q->next->next=NULL;}else{p->next=head;head=head->next;p->next->next=q;}}}return open;}void main(){int i,j;int key=0;node FirstNode;node *open, *close;node *p, *r;node *NodeList;printf("请输入初始状态的8数码(按每行从左往右依次输入,用0表示空格):\n");for(i=0; i<3; i++)for(j=0; j<3; j++)scanf("%d",&FirstNode.number[i][j]);printf("\n");printf("搜索树为:\n");for(i=0; i<3; i++){for(j=0; j<3; j++)printf("%d ",FirstNode.number[i][j]);printf("\n");}printf("\n");FirstNode.parent=(node *)malloc(sizeof(node));FirstNode.Depth=0;//开始结点深度为零FirstNode.W=CounterW(FirstNode.number);open=&FirstNode;p=&FirstNode;if(open->W == 0)//该结点的状态与目标结点相同{printf("该结点已为目标结点状态!\n");return;}r=&FirstNode;close=&FirstNode;r->next=NULL;open=NULL;NodeList=FindNextNode(r,open,close);//NodeList指向新扩展出来的链表open=insert(open,NodeList);//将扩展出来的结点插入到open表中while(open != NULL){r->next=open;//将open表的第一个元素加到close表,r始终指向close表的最后一个元素open=open->next;r=r->next;r->next=NULL;if(r->W == 0){key=1;printf("\n启发式搜索成功!\n");break;}NodeList=FindNextNode(r,open,close);;//对close表最后一个结点进行扩展,扩展得到的链表接到head表open=insert(open,NodeList);//将扩展的结点按顺序插入到open 表中}if(key == 1){p=close;printf("最优搜索过程如下:\n");printf("结点深度为:%d\n",FirstNode.Depth);printf("-------------\n");while(p!=NULL){for(i=0; i<3; i++){for(j=0; j<3; j++)printf("%d ",p->number[i][j]);printf("\n");}printf("\n");p=p->next;if(p != NULL)printf("结点深度为:%d\n",p->Depth);printf("-------------\n");}} elseprintf("查找失败,该问题无解!\n");}4.实验结果搜索树为:最短路径为:5.实验分析本次实验采用启发式搜索,利用C语言编写程序实现八数码问题的求解。