15数码问题的解决算法算法和具体代码

合集下载

十五数码问题研究及实现

十五数码问题研究及实现

转 换 成 如 何 从 初 始 排 列 开 始 .使 空 格 经 过 有 限 的移 动 次数 使 排
列 变 成 目标 排 列
3 问题 分 析 、
度 优 先搜 索 B S 另 一类 是启 发 式 搜 索 , A F: 如 算 法 。 对 于 十 五 数 码 问题 .深 度 优 先 搜 索 的状 态 空 间 搜 索 树 的 深 度 可 能 为无 限深 .或 者 可 能 至 少 要 比某 个 可 接 受 的 解 答 序 列 的 已 知 深度 上 限 还 要 深 。应 用 此 策 略 很 可 能 得 不 到 解[ 4 1 度 优 先 宽 搜 索 的优 势 在 于 当问 题 有 解 时 .一 定 能 找 到 解 ,且 能 找 到最 优 解 。 其 搜 索 时 需 要 保 存所 有 的 待扩 展 结 点 。 但 这样 很 容 易 扩 展 那 些 没 有 用 的结 点 , 成 状 态 的指 数 增 长 , 至 ” 合 爆 炸 ” 造 甚 组 。这 对 宽度 优 先 搜 索 很 不 利[ 这 两 种 搜 索 方 法 的 共 同 缺点 是 结 点 排 序 4 1 杂 乱 无 章 . 往 在 搜 索 了大 量 无 关 结 点 后 才 能 得 到 目的结 点 , 往 只 适 合 于 复 杂 度 较 低 的 问题 的求 解 。 启 发 式 搜 索 利 用 特 定 问 题 自身 所 携 带 的 启 发 信 息 在 一 定 程 度 上 避 免 了盲 目搜 索 的不 足 . 合 于 解决 十 五数 码 问题 。 核 心 适 其 思 想 是 引 入 一个 启 发 式 函数 ( 称 为评 估 函 数)利 用评 估 函 数 为 或 , 生 成 的 结 点 估 值 . 按 估 值 的 大 小 对 结 点 进 行 排 序 . 先 搜 索 估 并 优 值 小 的 结 点 。 评 估 函数 根 据 问 题 的 启 发 信 息 建立 . 估 了解 决 该 评 问 题 所 需 的最 小 费 用 , 基 本 形 式 是 : n =g ) () 其 中 g 其 “ 1 ( +hn。 n f : 初始 状 态 s到 中 间 状 态 n的 最 佳 代 价 g ( 的 估 值 ,() n从 ) n ) hn: 从 中 间 状 态 n到 目标 状 态 t 最 佳 代 价 h f1 估值 。利 用评 估 函 的 n的 数 来 进 行 的 图 搜 索 算 法 称 为 A 算 法 。 还 有 hn≤h () 称 为 若 () n则 A 算 法 。 在 八数 码 问题 中 , 常 是 搜 索树 中当前 结 点 n的深 度 , 通 是 从 根结 点 到 当前 结点 n的 最 短路 径 长 度 ;f的取 值 则 有 多种 这 hn 】 , 里 主 要 是 hn体 现 了 启 发 信 息 ,( 设 计 的好 坏 体 现 了算 法 的 ” () hn ) 智 能” 平 。本 文 借 鉴 这 些 算 法 并 结 合 十 五数 码 问题 的 特点 , 水 提 出 了 两个 新 的 hni数 。 C语 言 实 现 该 算 法 , 比较 了该 算 法 ()i 用  ̄ 并 与 常见 的 A 算 法 问 的 性 能 差异 。本 文 的 评 估 函数 f ) 取 如 f 分别 n

人工智能A星算法解决八数码难题程序代码

人工智能A星算法解决八数码难题程序代码

#include "Stdio.h"#include "Conio.h"#include "stdlib.h"#include "math.h"void Copy_node(struct node *p1,struct node *p2);void Calculate_f(int deepth,struct node *p);void Add_to_open(struct node *p);void Add_to_closed(struct node *p);void Remove_p(struct node *name,struct node *p);int Test_A_B(struct node *p1,struct node *p2);struct node * Search_A(struct node *name,struct node *temp); void Print_result(struct node *p);struct node // 定义8数码的节点状态{int s[3][3]; //当前8数码的状态int i_0; //当前空格所在行号int j_0; //当前空格所在列号int f; //当前代价值int d; //当前节点深度int h; //启发信息,采用数码"不在位"距离和struct node *father; //指向解路径上该节点的父节点struct node *next; //指向所在open或closed表中的下一个元素} ;struct node s_0={{2,8,3,1,6,4,7,0,5},2,1,0,0,0,NULL,NULL}; //定义初始状态struct node s_g={{1,2,3,8,0,4,7,6,5},1,1,0,0,0,NULL,NULL}; //定义目标状态struct node *open=NULL; //建立open表指针struct node *closed=NULL; //建立closed表指针int sum_node=0; //用于记录扩展节点总数//***********************************************************//********************** **********************//********************** 主函数开始**********************//********************** **********************//***********************************************************void main(){int bingo=0; //定义查找成功标志,bingo=1,成功struct node s; //定义头结点sstruct node *target,*n,*ls,*temp,*same; //定义结构体指针Copy_node(&s_0,&s); //复制初始状s_0态给头结点s Calculate_f(0,&s); //计算头结点的代价值Add_to_open(&s); //将头结点s放入open表while(open!=NULL) //只要open表不为空,进行以下循环{n=open; //n指向open表中当前要扩展的元素ls=open->next;Add_to_closed(n);open=ls; //将n指向的节点放入closed表中if(Test_A_B(n,&s_g)) //当前n指向节点为目标时,跳出程序结束;否则,继续下面的步骤{bingo=1;break;}elseif(n->j_0>=1) //空格所在列号不小于1,可左移{temp=n->father;if(temp!=NULL&&temp->i_0==n->i_0&&temp->j_0-1==n->j_0) //新节点与其祖父节点相同;else //新节点与其祖父节点不同,或其父节点为起始节点{temp=(struct node *)malloc(sizeof(struct node)); //给新节点分配空间Copy_node(n,temp); //拷贝n指向的节点状态temp->s[temp->i_0][temp->j_0]=temp->s[temp->i_0][temp->j_0-1]; //空格左移temp->s[temp->i_0][temp->j_0-1]=0;temp->j_0--;temp->d++;Calculate_f(temp->d,temp); //修改新节点的代价值temp->father=n; //新节点指向其父节点if(same=Search_A(closed,temp)) //在closed表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表{Remove_p(closed,same); //从closed表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else;}else if(same=Search_A(open,temp)) //在open表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比open表中相同状态节点代价小,加入open表{Remove_p(open,same); //从open表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else ;}else //新节点为完全不同的新节点,加入open表{Add_to_open(temp);sum_node++;}}}//end左移if(n->j_0<=1) //空格所在列号不大于1,可右移{temp=n->father;if(temp!=NULL&&temp->i_0==n->i_0&&temp->j_0+1==n->j_0) //新节点与其祖父节点相同;else //新节点与其祖父节点不同,或其父节点为起始节点{temp=(struct node *)malloc(sizeof(struct node)); //给新节点分配空间Copy_node(n,temp); //拷贝p指向的节点状态temp->s[temp->i_0][temp->j_0]=temp->s[temp->i_0][temp->j_0+1]; //空格右移temp->s[temp->i_0][temp->j_0+1]=0;temp->j_0++;temp->d++;Calculate_f(temp->d,temp); //修改新节点的代价值temp->father=n; //新节点指向其父节点if(same=Search_A(closed,temp)) //在closed表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表{Remove_p(closed,same); //从closed表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else;}else if(same=Search_A(open,temp)) //在open表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比open表中相同状态节点代价小,加入open表{Remove_p(open,same); //从open表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else ;}else //新节点为完全不同的新节点,加入open表{Add_to_open(temp);sum_node++;}}}//end右移if(n->i_0>=1) //空格所在列号不小于1,上移{temp=n->father;if(temp!=NULL&&temp->i_0==n->i_0-1&&temp->j_0==n->j_0) //新节点与其祖父节点相同;else //新节点与其祖父节点不同,或其父节点为起始节点{temp=(struct node *)malloc(sizeof(struct node)); //给新节点分配空间Copy_node(n,temp); //拷贝p指向的节点状态temp->s[temp->i_0][temp->j_0]=temp->s[temp->i_0-1][temp->j_0];//空格上移temp->s[temp->i_0-1][temp->j_0]=0;temp->i_0--;temp->d++;Calculate_f(temp->d,temp); //修改新节点的代价值temp->father=n; //新节点指向其父节点if(same=Search_A(closed,temp)) //在closed表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表{Remove_p(closed,same); //从closed表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else;}else if(same=Search_A(open,temp)) //在open表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比open表中相同状态节点代价小,加入open表{Remove_p(open,same); //从open表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else ;}else //新节点为完全不同的新节点,加入open表{Add_to_open(temp);sum_node++;}}}//end上移if(n->i_0<=1) //空格所在列号不大于1,下移{temp=n->father;if(temp!=NULL&&temp->i_0==n->i_0+1&&temp->j_0==n->j_0) //新节点与其祖父节点相同;else //新节点与其祖父节点不同,或其父节点为起始节点{temp=(struct node *)malloc(sizeof(struct node)); //给新节点分配空间Copy_node(n,temp); //拷贝p指向的节点状态temp->s[temp->i_0][temp->j_0]=temp->s[temp->i_0+1][temp->j_0]; //空格下移temp->s[temp->i_0+1][temp->j_0]=0;temp->i_0++;temp->d++;Calculate_f(temp->d,temp); //修改新节点的代价值temp->father=n; //新节点指向其父节点if(same=Search_A(closed,temp)) //在closed表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比closed表中相同状态节点代价小,加入open表{Remove_p(closed,same); //从closed表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else;}else if(same=Search_A(open,temp)) //在open表中找到与新节点状态相同的节点{if(temp->f<same->f) //temp指向的节点,其代价比open表中相同状态节点代价小,加入open表{Remove_p(open,same); //从open表中删除与temp指向节点状态相同的节点Add_to_open(temp);sum_node++;}else ;}else //新节点为完全不同的新节点,加入open表{Add_to_open(temp);sum_node++;}}}//end下移}if(bingo=1) Print_result(n); //输出解路径else printf("问题求解失败!");}//主函数结束//************************************************************************* //********************** ********************** //********************** 计算某个节点状态的代价值********************** //********************** ********************** //*************************************************************************void Calculate_f(int deepth,struct node *p){int i,j,temp;temp=0;for(i=0;i<=2;i++) //计算所有"不在位"数码的距离和{for(j=0;j<=2;j++){if((p->s[i][j])!=(s_g.s[i][j]))temp++;}}p->h=temp;p->f=deepth+p->h;}//*************************************************************************//********************** **********************//********************** 添加p指向的节点到open表中********************** //********************** **********************//*************************************************************************void Add_to_open(struct node *p){struct node *p1,*p2;p1=open; //初始时p1指向open表首部p2=NULL;if(open==NULL) //open表为空时,待插入节点即为open表第一个元素,open 指向该元素{p->next=NULL;open=p;}else //open表不为空时,添加待插入节点,并保证open表代价递增的排序{while(p1!=NULL&&p->f>p1->f){p2=p1; //p2始终指向p1指向的前一个元素p1=p1->next;}if(p2==NULL) //待插入节点为当前open表最小{p->next=open;open=p;}else if(p1==NULL) //待插入节点为当前open表最大{p->next=NULL;p2->next=p;}else //待插入节点介于p2、p1之间{p2->next=p;p->next=p1;}}}//***************************************************************************//********************** **********************//********************** 添加p指向的节点到closed表中**********************//********************** **********************//***************************************************************************void Add_to_closed(struct node *p){if(closed==NULL) //closed表为空时,p指向节点为closed表第一个元素,closed{p->next=NULL;closed=p;}else //closed表不为空时,直接放到closed表首部{p->next=closed;closed=p;}}//************************************************************************************* *************//********************************************//********************** 在open表或closed表中搜索和temp指向的节点相同的节点**********************//********************************************//*************************************************************************************struct node * Search_A(struct node *name,struct node *temp){struct node *p1;p1=name; //p1指向open表或closed表while(p1!=NULL){if(Test_A_B(p1,temp)) //找到相同的节点,返回该节点地址return p1;elsep1=p1->next;}return NULL;}//************************************************************************************* **********//********************************************//********************** 判断两个节点状态是否相同,相同则返回1,否则返回0 **********************//********************************************//************************************************************************************* **********int Test_A_B(struct node *p1,struct node *p2){int i,j,flag;flag=1;for(i=0;i<=2;i++)for(j=0;j<=2;j++){if((p2->s[i][j])!=(p1->s[i][j])) { flag=0; return flag; }else ;}return flag;}//******************************************************************************//********************** **********************//********************** 从open表或closed表删除指定节点********************** //********************** **********************//******************************************************************************void Remove_p(struct node *name,struct node *p){struct node *p1,*p2;p1=NULL;p2=NULL;if(name==NULL) //如果name指向的链表为空,则不需要进行删除return;else if(Test_A_B(name,p)&&name->f==p->f) //指定节点为name指向的链表的第一个元素{open=name->next;name->next=NULL;return;}else{p2=name;p1=p2->next;while(p1){if(Test_A_B(p1,p)&&p1->f==p->f) //找到指定节点{p2->next=p1->next;return;}else{p2=p1; //p2始终指向p1指向的前一个元素p1=p1->next;}}return;}}//************************************************************************************* *//********************************************//********************** 将p1指向的节点状态拷贝到p2指向的节点中**********************//********************************************//************************************************************************************* *void Copy_node(struct node *p1,struct node *p2){int i,j;for(i=0;i<=2;i++){for(j=0;j<=2;j++){ p2->s[i][j]=p1->s[i][j]; }}p2->i_0=p1->i_0;p2->j_0=p1->j_0;p2->f=p1->f;p2->d=p1->d;p2->h=p1->h;p2->next=p1->next;p2->father=p1->father;}//*********************************************************** //********************** ********************** //********************** 输出结果********************** //********************** ********************** //***********************************************************void Print_result(struct node *p){struct node *path[100];struct node *temp,*temp_father;int i,j,k;for(i=0;i<=99;i++) //初始化路径指针数组path[i]=0;temp=p;printf("总共扩展%d 个节点\n",sum_node);printf("总共扩展%d 层\n",temp->d);printf("解路径如下:\n");for(i=p->d;i>=0;i--) //存储解路径上各节点的地址{path[i]=temp;temp=temp->father;}for(k=0;k<=p->d;k++) //输出解路径{temp=path[k]; //建立节点指点指针printf("第%d步",temp->d);if(k-1>=0) //输出移动策略{temp_father=path[k-1];if(temp->i_0<temp_father->i_0) printf("->上移\n");if(temp->i_0>temp_father->i_0) printf("->下移\n");if(temp->j_0<temp_father->j_0) printf("->左移\n");if(temp->j_0>temp_father->j_0) printf("->右移\n");}elseprintf("\n");printf("当前节点状态为:\n");for(i=0;i<=2;i++){for(j=0;j<=2;j++){printf("%d ",temp->s[i][j]);}printf("\n");}printf("\n");}}THANKS !!!致力为企业和个人提供合同协议,策划案计划书,学习课件等等打造全网一站式需求欢迎您的下载,资料仅供参考。

15数码问题解法

15数码问题解法

15数码问题解法The 15-puzzle is a classic sliding puzzle that consists of 15 numbered tiles on a 4x4 grid with one empty space. The goal is to arrange the tiles in numerical order by sliding them into the empty space. It might seem like a simple task, but the puzzle can be quite challenging and require strategic thinking to solve.15数码问题是经典的滑动拼图,由4x4网格上的15个编号瓦片和一个空格组成。

目标是通过将瓦片滑入空格来按数字顺序排列瓦片。

这个谜题看起来可能很简单,但是解决这个问题可能会很有挑战性,需要策略性的思维来解决。

One approach to solving the 15-puzzle involves creating a solving strategy that prioritizes certain moves over others. By identifying patterns and common sequences of moves, you can improve your efficiency in solving the puzzle. This can help you avoid getting stuck in dead-end positions and find the most efficient path to completing the puzzle.解决15数码问题的一种方法是创建一个解决策略,优先考虑某些移动而不是其他移动。

奥数 数码问题(完整资料).doc

奥数 数码问题(完整资料).doc

此文档下载后即可编辑数码问题姓名:知识点拨我们知道,用来记数的符号叫做数字,而数字是指0、1、2、3、4、5、6、7、8、9这10个阿拉伯数字,它们也是当今世界各国通用的数字。

这10个阿拉伯数字叫做数码。

它是印度人首先使用的。

记数时,常常把数字(或数码)并排成横列,组成一个多位数。

如567是由5个百、6个十、7个一组成的。

这就是说,数中的每个数字除了它本身所表示的数值以外,还有位置值,这样的计数原则称为位置原则。

因此,每个数都可以写成这个数各数位上的数字与所在数位的计数单位的积再求和的形式。

如567 =在学习和日常生活中,经常研究“数”与“组成它的数码”之间的关系,这类问题我们称为数码问题,数码问题也可以借助横竖式数字谜来解答。

经典例题【例1】一个两位数,个位数字是十位数字的3倍。

如果这个数加上5,则两个数字就相同。

求这个两位数。

【巩固】一个两位数,个位数字是十位数字的4倍。

如果这个数加上5,则两个数字相同。

这个两位数是多少?【例2】一个两位数,十位数字是个位数字的4倍。

如果这个数减去5,则两个数字就相同,求这个两位数。

【巩固】一个两位数,十位数字是个位数字的3倍。

如果这个数减去7,则两个数字相同。

这个两位数是多少?【例3】一个两位数,其各位数字之和是7。

如果此数减去27,则两个数字的位置交换,求原来的两位数。

【巩固】一个三位数,个位上数字是4,如果将这个数的个位上数字与百位上数字数字调换,则得到的新数比原数小297,原数是多少?【例4】5个连续自然数的和是100,求这5个数的各位数字之和是多少。

【例5】某三位数是9的倍数,且在300~400之间,它的百位数字与个位数字的和是10,这个三位数是多少?【巩固】在一个两位数的右端添上“6”则这个数增加了600,这个数是多少?【例6】一个数减去2487,小明计算时错把被减数百位和十位上的数字互换了,结果是8439,正确得数是多少?【巩固】一个数减去3523,小英计算时错把被减数百位和十位上的数字互换了,结果得9423,正确得数是多少?过手训练1、一个两位数,其各位数字之和是10,数字之差是6,个位数字小于十位数字。

人工智能十五数码实验报告

人工智能十五数码实验报告

目录1 实验概述 (2)2 十五数码问题分析 (2)2.1十五数码问题简介 (2)2.2可行性分析 (3)3问题的求解策略 (3)3.1算法分析 (3)3.2 A*算法设计 (4)4 实验总结 (5)4.1 实验可视化界面 (5)4.2个人体会 (7)4.3 详细代码: 71 实验概述十五数码问题来源于美国的科学魔术大师萨姆.洛伊德(Sam I.oyd)在1978年推出的著名的“14-15”智力玩具。

这个游戏曾经风靡欧美大陆" 。

洛伊德的发明其实只是将重排九宫(即八数码问题)中的3阶方阵扩大到4 阶方阵罢了。

由于这个细微的变化, 十五数码问题的规模远远大于八数码问题, 八数码问题的规模较小, 总的状态数为9!(=362880)个, 而十五数码问题的状态,数为16!()个。

故十五数码问题更能评价一个算法的“智能”水平。

2 十五数码问题分析2.1十五数码问题简介15数码问题又叫移棋盘问题, 是人工智能中的一个经典问题。

所谓的15数码问题: 就是在一个4×4的16宫格棋盘上, 摆放有15个将牌, 每一个将牌都刻有1~15中的某一个数码。

棋盘中留有一个空格, 允许其周围的某一个将牌向空格移动, 这样通过移动将牌就可以不断改变将牌的布局。

这种求解的问题是: 给定一种初始的将牌布局或结构(称初始状态)和一个目标布局(称目标状态), 问如何移动数码, 实现从初始状态到目标状态的转变, 如下图所示。

问题的实质就是寻找一个合法的动作序列2.2可行性分析十五数码问题存在无解的情况,当遍历完所有可扩展的状态也没有搜索到目标状态就判断为无解。

可以根据状态的逆序数来先验的判断是否有解,当初始状态的逆序数和目标状态的逆序数的奇偶性相同时,问题有解;否则问题无解。

状态的逆序数是定义如下: 把四行数展开排成一行,并且丢弃数字0 不计入其中,ηi是第i 个数之前比该数小的数字的个数,则η=Σηi 是该状态的逆序数,例如: 对于初始状态: 5.1.2.4.9、 6.3.8、13.15.10、11.14.7、12.其η=0+0+1+2+4+4+2+6+8+9+8+9+11+6+11=81;对于目标状态: 1.2.3.4.5.6.7、8、9、10、11.12.13.14.15, 其η=0+1+2+3+4+5+6+7+8+9+10+11+12+13+14=105。

用A算法解决十五数码问题

用A算法解决十五数码问题

精心整理一、15数码问题的描述及其状态空间法表示(1)15数码问题描述15数码问题又叫移棋盘问题,是人工智能中的一个经典问题。

所谓的15数码问题:就是在一个4×4的16宫格棋盘上,摆放有15个将牌,每一个将牌都刻有1~15中的某一个数码。

棋盘中留有一个空格,允许其周围的某一个将牌向空格移动,这样通过移动将牌就可以不断改变将牌的布局。

这种求解的问题是:给定一种初始的将牌布局或结构(称初始状态)和一个目标布局(称目标状态),问如何移动数码,实现从初始状态到目标状态的转变,如图1所示。

问题的实质就是寻找一个合法的目标状态集合。

十五数码的状态空间法:初始状态S[4][4]={5,12,11,4,13,6,3,10,14,2,7,9,1,15,0,8};(0表示空格)目标状态G[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0};操作符集合F={空格上移,空格下移,空格左移,空格右移}状态空间的一个解:是一个有限的操作算子序列,它使初始状态转化为目标状态:S0-f1->S1-f2->...fk->G。

二、A*算法的基本原理、算法步骤、流程图(1)A*算法基本原理A*算法是一种有序搜索算法,其特点在于对评价函数的定义上。

对于一般的有序搜索,总是选择f值最小的节点作为扩展节点。

因此,f是根据需要找到一条最小代价路径的观点来估算节点的,可考虑将每个节点n的估价函数值分解为两个分量:从起始节点到节点n的最小代价路径的代价与从节点n到目标节点的最小代价路径的代价之和,也就是说f(n)是约束通过节点n的一条最小代价路径的代价的一个估计。

再定义一个函数f*,使得在任意一个节点n上的函数值f*(n)就是从节点S到节点n的一条最佳路径的实际代价加上从节点n到目标节点的一条最佳路径的代价之和,即:***在第7步中,如果搜索过程发现一条路径到达一个节点的代价比现存的路径代价低,就要重定向指向该节点的指针。

得出“15选5”的各种组合(组合生成算法)

得出“15选5”的各种组合(组合生成算法)

得出“15选5”的各种组合(组合生成算法)组合是指从一个给定的集合中选取若干个元素的方式,组合生成算法是通过遍历集合中所有可能的组合,得出所有可能的组合结果。

在15选5这个游戏中,规则是从1到15的数字中选出任意5个数字的组合。

下面是一种实现组合生成算法的方法,通过递归和回溯来得出所有可能的组合。

代码示例如下:
```
if k == 0:
results.append(result[:])
return
for i in range(start, len(arr)):
result.append(arr[i])
result.pop
results = []
return results
numbers = list(range(1, 16))
```
最后的循环用于遍历所有可能的组合,并输出结果。

通过运行上述代码,可以得到15选5这个游戏的所有可能的组合结果,共有3003个组合。

人工智能——十五数码解读

人工智能——十五数码解读

利用状态空间法解决十五数码游戏问题学号19110227 姓名季佳辉完成时间2013年11 月1.十五数码游戏简介十五数码游戏问题是在4*4方格盘上,放有15个数码,剩下第16个为空,每一空格其上下左右的数码可移至空格。

问题给定初始位置和目标位置,要求通过一系列的数码移动,将初始位置转化为目标位置。

2.十五数码游戏问题的状态空间法表示问题的状态空间是指表示问题可能态及关系图,记作三元态(S,F,G)。

它含三个集合:初始态集S;操作符集F;目标态集G。

十五数码问题状态空间法:初始态S[4][4]={5,1,2,4,9,6,3,8,13,10,7,11,0,14,15,12}。

目标态G[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0}(0表示空格)。

操作符集F=[空格左移、上移、右移、下移],实现状态转换。

3.十五数码游戏问题的盲目搜索技术1. 宽度优先搜索如果搜索是以接近起始节点的程度依次扩展节点的,那么这种搜索就叫做宽度优先搜索。

这种搜索是逐层进行的;在对下一层的任一节点进行搜索之前,必须搜索完本层的所有节点。

其搜索过程如图(1)所示。

图1 宽度优先搜索示意图宽度优先搜索算法如下:(1)把起始节点放到OPEN 表中(如果该起始节点为一目标节点,则得到解) (2)如果OPEN 是个空表,则无解,失败退出;否则继续下一步(3)把第一个节点(记作节点n )从OPEN 表移出,并把它放入CLOSED 的已扩展节点表中(4)扩展节点n 。

如果没有后继节点,则转向第(2)步(5)把n 的所有后继节点放到OPEN表的末端,并提供从这些后继节点回到n 的指针(6)如果n 的任一个后继节点是个目标节点,则找到一个解(反向追踪得到从目标节点到起始节点的路径),成功退出,否则转向第(2)步其流程图如图2所示图2 宽度优先算法流程图2、深度优先搜索在深度优先搜索中,首先扩展最新产生的(即最深的)节点。

启发式搜索算法解决八数码问题(C语言)

启发式搜索算法解决八数码问题(C语言)

1、程序源代码#include <stdio.h>#include<malloc.h>struct node{int a[3][3];//用二维数组存放8数码int hx;//函数h(x)的值,表示与目标状态的差距struct node *parent;//指向父结点的指针struct node *next;//指向链表中下一个结点的指针};//------------------hx函数-------------------//int hx(int s[3][3]){//函数说明:计算s与目标状态的差距值int i,j;int hx=0;int sg[3][3]={1,2,3,8,0,4,7,6,5};for(i=0;i<3;i++)for(j=0;j<3;j++)if(s[i][j]!=sg[i][j])hx++;return hx;}//-------------hx函数end----------------------////-------------extend扩展函数----------------//struct node *extend(node *ex){ //函数说明:扩展ex指向的结点,并将扩展所得结点组成一条//单链表,head指向该链表首结点,并且作为返回值int i,j,m,n; //循环变量int t; //临时替换变量int flag=0;int x[3][3];//临时存放二维数组struct node *p,*q,*head;head=(node *)malloc(sizeof(node));//headp=head;q=head;head->next=NULL;//初始化for(i=0;i<3;i++)//找到二维数组中0的位置{for(j=0;j<3;j++)if(ex->a[i][j]==0){flag=1;break;}if(flag==1)break;}for(m=0;m<3;m++)//将ex->a赋给xfor(n=0;n<3;n++)x[m][n]=ex->a[m][n];//根据0的位置的不同,对x进行相应的变换//情况1if(i-1>=0){t=x[i][j];x[i][j]=x[i-1][j];x[i-1][j]=t;flag=0;for(m=0;m<3;m++)//将x赋给afor(n=0;n<3;n++)if(x[m][n]==ex->parent->a[m][n])flag++;if(flag!=9){q=(node *)malloc(sizeof(node));for(m=0;m<3;m++)//将x赋给afor(n=0;n<3;n++)q->a[m][n]=x[m][n];q->parent=ex;q->hx=hx(q->a);q->next=NULL;p->next=q;p=p->next;}}//情况2for(m=0;m<3;m++)//将ex->a重新赋给x,即还原x for(n=0;n<3;n++)x[m][n]=ex->a[m][n];if(i+1<=2){t=x[i][j];x[i][j]=x[i+1][j];x[i+1][j]=t; flag=0;for(m=0;m<3;m++)for(n=0;n<3;n++)if(x[m][n]==ex->parent->a[m][n])flag++;if(flag!=9){q=(node *)malloc(sizeof(node));for(m=0;m<3;m++)//将x赋给afor(n=0;n<3;n++)q->a[m][n]=x[m][n];q->parent=ex;q->hx=hx(q->a);q->next=NULL;p->next=q;p=p->next;}}//情况3for(m=0;m<3;m++)//将ex->a重新赋给x,即还原x for(n=0;n<3;n++)x[m][n]=ex->a[m][n];if(j-1>=0){t=x[i][j];x[i][j]=x[i][j-1];x[i][j-1]=t;flag=0;for(m=0;m<3;m++)for(n=0;n<3;n++)if(x[m][n]==ex->parent->a[m][n])flag++;if(flag!=9){q=(node *)malloc(sizeof(node));for(m=0;m<3;m++)//将x赋给afor(n=0;n<3;n++)q->a[m][n]=x[m][n];q->parent=ex;q->hx=hx(q->a);q->next=NULL;p->next=q;p=p->next;}}//情况4for(m=0;m<3;m++)//将ex->a重新赋给x,即还原xfor(n=0;n<3;n++)x[m][n]=ex->a[m][n];if(j+1<=2){t=x[i][j];x[i][j]=x[i][j+1];x[i][j+1]=t;flag=0;for(m=0;m<3;m++)for(n=0;n<3;n++)if(x[m][n]==ex->parent->a[m][n])flag++;if(flag!=9){q=(node *)malloc(sizeof(node));for(m=0;m<3;m++)for(n=0;n<3;n++)q->a[m][n]=x[m][n];q->parent=ex;q->hx=hx(q->a);q->next=NULL;p->next=q;p=p->next;}}head=head->next;return head;}//---------------extend函数end-----------------------////----------------insert函数-------------------------//node* insert(node *open,node * head){ //函数说明:将head链表的结点依次插入到open链表相应的位置, //使open表中的结点按从小到大排序。

15数码问题的解决算法

15数码问题的解决算法

〈〈人工智能〉〉题目:15数码问题实验1:要求:采用广度优先算法解决15数码问题,输出扩展结点,步数和最终结果算法描述:广度优先搜索,即BFS(Breadth First Search),常常深度优先并列提及。

这是一种相当常用的图算法,其特点是:每次搜索指定点,并将其所有未访问过的近邻加入搜索队列(而深度优先搜索则是栈),循环搜索过程直到队列为空。

广度优先搜索算法的基本思想:从初始状态出发,按照给定的结点产生式规则(算符、结点扩展规则)生产第一层结点,每生成一个结点就检查是不是目标结点,如果是目标结点就搜索结束,如果不是目标结点并且前面没出现过就保存该结点(入队列);再用产生式规则将所有第一层的结点依次扩展,得到第二层结点,同时检查是否为目标结点,是目标搜索停止,不是并且没出现过保存(入队);再把第二层的结点按产生规则扩展生产第三层结点,直至找到目标或所有的状态找完但找不到目标(队列空)。

特点:先生成深度为1的所有结点,再生产深度为2的所有结点,依次类推。

先横向,再纵向。

这种方法找到目标,需要的步数一定最少。

程序算法流程图:描述:(1).把起始结点放到OPEN表中。

(2).如果OPEN表是个空表,则没有解,失败退出;否则继续。

(3).把第一个结点从OPEN表中移出,并把它放入CLOSE表的扩展节点表中。

(4).扩展结点N。

如果没有后继结点,则转向步骤(2)。

(5).把N的所有后继结点放到OPEN表的末端,并提供从这些后继结点回到N的指针。

(6).如果N的任意个后继结点是个目标结点,则找到一个解答,成功退出;否则转向步骤(2).流程图:输入:初始态int A[N][N]={{1,2,3,4},{5,10,6,8},{0,9,7,12},{13,14,11,15}};目标状态:int B[N][N]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};输出截图:由于输出的路径节点很多这里只是显示最终结果和步数。

应用状态空间法解决十五数码问题

应用状态空间法解决十五数码问题
维普资讯
科 苑 论谈 ff f
严长虹 金 琳

应用状 态 空 问法解 决十五 数 码 问题
( 苏州大学 盐城 工学院, 江苏 苏州 2 5 2 ) 10 1
摘 要: 十五数码是人工智能 中重要 问题。解决该 问题对 十五数码作分析 , 再基 于状 态空 间法用有序算法解决 , 经实验检验有效。 最后 关键词 : 十五数码问题 ; 态空间法; 状 有序 算法
f , 1 ,4 5 ,2 ,9 ,6 ,3 ,8 1 , 1 , , 3 0
7, l , O, l 1 4, l 5, l 2l
fr( Oi4i+ o i ; ; ) = < + o = d4 +) frG O < d + i s i [] s i [] f( l[] j !=2[J j & s i 0) & l[ J J h +; n+ rtm eu h; n } s e uls it l[ ] [ ] , n q a i n s 4 4 s l t( n h a) , ed / 判断链表 中是否有相 同的棋局 ( s p= ed n sh a ; w i p l= UL ) hl s N L e(
弓l 言 十 五数码 是人工智 能 中重要 问题 。解决 该 问题先对十五数码作分析 ,再基 于状态 空间 法用有序算法解决 ,最后经实验检验有效 。给 出了主要 的算法实现 ( V + 描写)和结果 。 用 c+ 1十五数码 问题 的文字 描述及状 态空 间 法表示 11文字描述 : . 一个 4 4方格盘放 1 1 x ~ 5个 数码 ,空格 四周数码可移 至空格 。问题 :从某 初始局移动空格至 目标局 。
( i !cm ae(l s >) rtr s f( o p r s, 一 s p ) eu p; n

10个经典的算法问题与解决方案

10个经典的算法问题与解决方案

10个经典的算法问题与解决方案算法问题是计算机科学中非常重要的一部分,对于准备面试或提升自己的技能都是很有帮助的。

下面列举了10个经典的算法问题及其解决方案:1.两数之和(Two Sum)问题描述:给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

解决方案:使用哈希表记录每个数字的索引,然后遍历数组,查找目标值减当前数的差是否存在于哈希表中。

2.盛最多水的容器(Container With Most Water)问题描述:给定一个非负整数数组,数组中的每个表示一条柱子的高度,找出两个柱子,使得它们与x轴构成的容器可以容纳最多的水。

解决方案:维护两个指针,分别指向数组的开始和结尾,计算当前指针所指的两条柱子之间的面积,并更新最大面积。

然后移动指向较小柱子的指针,重复计算直到两个指针相遇。

3.三数之和(3Sum)问题描述:给定一个整数数组,找出数组中所有不重复的三个数,使得它们的和为0。

解决方案:首先对数组进行排序,然后固定一个数字,使用双指针在剩余的数字中寻找另外两个数使得它们的和为相反数。

4.最大子序和(Maximum Subarray)问题描述:给定一个整数数组,找到一个具有最大和的连续子数组(子数组最少包含一个元素)。

解决方案:使用动态规划的思想,从数组的第一个元素开始依次计算以当前位置结尾的子数组的最大和,并保存最大值。

5.二分查找(Binary Search)问题描述:给定一个排序的整数数组和一个目标值,使用二分查找算法确定目标值是否存在于数组中,并返回其索引。

解决方案:通过比较目标值与数组的中间元素来确定目标值是在左半部分还是右半部分,并更新搜索范围进行下一轮查找。

6.背包问题(Knapsack Problem)问题描述:给定一组物品和一个背包,每个物品都有自己的重量和价值,在不超过背包容量的情况下,找到一个组合使得总价值最大化。

解决方案:使用动态规划的思想,定义一个二维数组表示背包容量和物品数量,从左上角开始计算每个格子可以放置的最大价值。

15数码问题的解决算法算法和具体代码

15数码问题的解决算法算法和具体代码

〈〈人工智能〉〉题目:15数码问题实验1:要求:采用广度优先算法解决15数码问题,输出扩展结点,步数和最终结果算法描述:广度优先搜索,即BFS(Breadth First Search),常常深度优先并列提及。

这是一种相当常用的图算法,其特点是:每次搜索指定点,并将其所有未访问过的近邻加入搜索队列(而深度优先搜索则是栈),循环搜索过程直到队列为空。

广度优先搜索算法的基本思想:从初始状态出发,按照给定的结点产生式规则(算符、结点扩展规则)生产第一层结点,每生成一个结点就检查是不是目标结点,如果是目标结点就搜索结束,如果不是目标结点并且前面没出现过就保存该结点(入队列);再用产生式规则将所有第一层的结点依次扩展,得到第二层结点,同时检查是否为目标结点,是目标搜索停止,不是并且没出现过保存(入队);再把第二层的结点按产生规则扩展生产第三层结点,直至找到目标或所有的状态找完但找不到目标(队列空)。

特点:先生成深度为1的所有结点,再生产深度为2的所有结点,依次类推。

先横向,再纵向。

这种方法找到目标,需要的步数一定最少。

程序算法流程图:描述:(1).把起始结点放到OPEN表中。

(2).如果OPEN表是个空表,则没有解,失败退出;否则继续。

(3).把第一个结点从OPEN表中移出,并把它放入CLOSE表的扩展节点表中。

(4).扩展结点N。

如果没有后继结点,则转向步骤(2)。

(5).把N的所有后继结点放到OPEN表的末端,并提供从这些后继结点回到N的指针。

(6).如果N的任意个后继结点是个目标结点,则找到一个解答,成功退出;否则转向步骤(2).流程图:输入:初始态int A[N][N]={{1,2,3,4},{5,10,6,8},{0,9,7,12},{13,14,11,15}};目标状态:int B[N][N]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};输出截图:由于输出的路径节点很多这里只是显示最终结果和步数。

数字的问题解决策略掌握解决数字问题的策略和方法

数字的问题解决策略掌握解决数字问题的策略和方法

數字的問題解決策略掌握解決數字問題的策略和方法数字的问题解决策略:掌握解决数字问题的策略和方法在日常生活和学习中,我们经常会遇到各种各样与数字相关的问题。

无论是计算、统计、推理还是分析,解决数字问题需要一定的策略和方法。

本文将介绍一些常用的数字问题解决策略,帮助读者更好地应对各类数字问题。

一、整体与局部解决数字问题时,首先要理清整体与局部的关系。

有时,一个问题给出的数字和条件较为复杂,此时我们可以通过分解整体和关注局部来解决问题。

例如,求一个数的平方根时,可以先逼近整个数的范围,再对局部进行逼近;又如,统计一个班级的成绩时,可以先统计每个学生的成绩,再整合到整体。

二、抽象与实际数字问题往往需要将抽象的概念和实际情况相结合。

通过将问题中的数字进行抽象,可以更好地理解问题的本质,并找到解决问题的方法。

例如,一个经典的应用是带入具体数值进行计算,通过不同数值的验证来确定答案的准确性。

此外,可以将数字与图形、图表等形式相结合,以更直观的方式解决数字问题。

三、等式与不等式在解决一些带有约束条件的数字问题时,等式和不等式常常是解题的基本工具。

建立合适的等式或不等式方程,可以将问题转化为容易求解的形式。

例如,有关长度和宽度的关系问题可以通过建立等式或不等式来求解,使问题更具可操作性,进而得到解题思路。

四、归纳与递推归纳与递推是解决数字问题的重要方法之一。

当问题中的数字规律不明显或难以解析时,我们可以通过寻找其中的规律,进而把握住问题的关键。

例如,求解一个数列的第n项,可以通过找到数列的通项公式,从而递推得到结果。

五、试错与验证解决数字问题时,试错与验证也是常用的策略之一。

我们可以选择一些合适的数字进行尝试,验证求解的过程与结果是否符合要求。

这样,可以在不确定的情况下逐步逼近准确答案,提高解题的准确性。

尤其是在较为复杂的问题中,试错与验证可以避免中途出错并及时纠正。

六、与他人交流数字问题解决的策略与方法可以与他人进行交流和分享。

《人工智能及其应用》实验指导书

《人工智能及其应用》实验指导书

《人工智能及其应用》实验指导书浙江工业大学计算机科学与技术学院—人工智能课程组2011年9月前言本实验是为了配合《人工智能及其应用》课程的理论学习而专门设置的。

本实验的目的是巩固和加强人工智能的基本原理和方法,并为今后进一步学习更高级课程和信息智能化技术的研究与系统开发奠定良好的基础。

全书共分为八个实验:1.产生式系统实验;2.模糊推理系统实验;3.A*算法求解8数码问题实验;4.A*算法求解迷宫问题实验;5.遗传算法求解函数最值问题实验;6.遗传算法求解TSP问题实验;7.基于神经网络的模式识别实验;8.基于神经网络的优化计算实验。

每个实验包括有:实验目的、实验内容、实验条件、实验要求、实验步骤和实验报告等六个项目。

本实验指导书包括两个部分。

第一个部分是介绍实验的教学大纲;第二部分是介绍八个实验的内容。

由于编者水平有限,本实验指导书的错误和不足在所难免,欢迎批评指正。

人工智能课程组2011年9月目录实验教学大纲 (1)实验一产生式系统实验 (3)实验二模糊推理系统实验 (5)实验三A*算法实验I (9)实验四A*算法实验II (12)实验五遗传算法实验I (14)实验六遗传算法实验II (18)实验七基于神经网络的模式识别实验 (20)实验八基于神经网络的优化计算实验 (24)实验教学大纲一、学时:16学时,一般安排在第9周至第16周。

二、主要仪器设备及运行环境:PC机、Visual C++ 6.0、Matlab 7.0。

三、实验项目及教学安排序号实验名称实验平台实验内容学时类型教学要求1 产生式系统应用VC++ 设计知识库,实现系统识别或分类等。

2 设计课内2 模糊推理系统应用Matlab 1)设计洗衣机的模糊控制器;2)设计两车追赶的模糊控制器。

2 验证课内3 A*算法应用I VC++ 设计与实现求解N数码问题的A*算法。

2 综合课内4 A*算法应用II VC++ 设计与实现求解迷宫问题的A*算法。

十五数码

十五数码

A*算法实验I-十五数码班级:计自1202班学号:201226100531 姓名:赵玮瑄一、实验目的在八数码的基础上写出十五数码的问题,熟悉掌握A*算法的运算过程。

进一步理解求解过程和求解次序。

二、实验原路A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上。

对于一般的启发式图搜索,总是选择估价函数f值最小的节点作为扩展节点。

因此,f是根据需要找到一条最小代价路径的观点来估算节点的,所以,可考虑每个节点n的估价函数值为两个分量:从起始节点到节点n的实际代价g(n)以及从节点n到达目标节点的估价代价h(n),且)h ,)(*nh为n节点到目的结点的最优路径的代n)(*(nh价。

十六数码问题是在4×4的十六宫格棋盘上,摆有16个刻有1~F数码的将牌。

棋盘中有一个空格,允许紧邻空格的某一将牌可以移到空格中,这样通过平移将牌可以将某一将牌布局变换为另一布局。

针对给定的一种初始布局或结构(目标状态),问如何移动将牌,实现从初始状态到目标状态的转变。

三、实验结果三种估价函数:源代码:int calw(string s)//计算该状态的不在位数h(n){int re=0;for(int i=0;i<16;i++) if(s[i]!=t[i] && s[i]!='0') re++;return re;}int calw1(string s)//自定义估价函数,是各数码移到目的位置所需移动的距离的总和{int re=0;for(int i=0;i<9;i++){ i f(s[i]!=t[i] && s[i]!='0'){ for(int j=0;j<9;j++){if(s[i]==t[j]) break;}re+=abs(i/3-j/3)+abs(i%3-j%3);}}return re;}int calw2(string s)//宽度优先搜索算法(即令估计代价h(n)=0的A*算法){return 0;}表1 不同启发函数h(n)求解十五数码问题的结果比较四、实验总结总的来说,十五数码的基本运算过程与八数码是相同的,基本的运算机理也是差不多的,运算的方法也基本一致,但是运算量却比八数码的运算量大很多。

用A算法解决十五数码问题 (1)

用A算法解决十五数码问题 (1)

一、15数码问题的描述及其状态空间法表示(1)15数码问题描述15数码问题又叫移棋盘问题,是人工智能中的一个经典问题。

所谓的15数码问题:就是在一个4×4的16宫格棋盘上,摆放有15个将牌,每一个将牌都刻有1~15中的某一个数码。

棋盘中留有一个空格,允许其周围的某一个将牌向空格移动,这样通过移动将牌就可以不断改变将牌的布局。

这种求解的问题是:给定一种初始的将牌布局或结构(称初始状态)和一个目标布局(称目标状态),问如何移动数码,实现从初始状态到目标状态的转变,如图1所示。

问题的实质就是寻找一个合法的动作序列(a)初始状态(b)目标状态图1 15数码问题的一个实例(2)状态空间法表示人工智能问题的求解是以知识表示为基础的。

如何将已获得的有关知识以计算机内部代码形式加以合理地描述、存储、有效地利用便是表示应解决的问题[1]。

目前的知识表示方法有十余种,如:一阶谓词逻辑表示法、产生式表示法、状态空间表示法、语义网格表示法、框架表示法、脚本表示法、面向对象表示法等。

任何一个给定的问题可能存在多种知识表示方法,人们可以根据待求解问题的领域知识选择适当的知识表示方法。

这里我们只强调状态空间表示法。

把求解的问题表示成问题状态、操作、约束、初始状态和目标状态。

状态空间就是所有可能的状态的集合。

求解一个问题就是从初始状态出发,不断应用可应用的操作,在满足约束的条件下达到目标状态。

问题求解过程就可以看成是问题状态在状态空间的移动。

状态是为描述某类不同事物间的差别而引入的一组最少变量q0,q1,…,q n的有序集合。

问题的状态空间是一个表示该问题全部可能状态及其关系的图。

记为三元状态(S、F、G),其中S所有可能的问题初始状态集合,F操作符集合,G目标状态集合。

十五数码的状态空间法:初始状态S[4][4]={5,12,11,4,13,6,3,10,14,2,7,9,1,15,0,8};(0表示空格)目标状态G[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0};操作符集合F={空格上移,空格下移,空格左移,空格右移}状态空间的一个解:是一个有限的操作算子序列,它使初始状态转化为目标状态:S0-f1->S1-f2->...f k->G。

15的八位二进制反码

15的八位二进制反码

任务名称:15的八位二进制反码一、什么是二进制反码二进制反码是一种用于表示数字的编码方式。

在二进制反码中,正数的反码与原码相同,而负数的反码是将其原码中所有位取反(0变为1,1变为0)得到的。

二、十进制数15的二进制表示在二进制中,十进制数15的二进制表示为1111。

三、十进制数15的八位二进制反码表示根据二进制反码的定义,十进制数15的八位二进制反码表示为00001111。

四、二进制反码的应用二进制反码在计算机科学和电子工程中有广泛的应用。

以下是一些常见的应用场景:1. 补码表示二进制反码是计算机中常用的表示负数的方式。

计算机使用补码表示负数,其中正数的补码与原码相同,而负数的补码是将其原码的二进制反码加1得到的。

2. 数据传输在计算机中,数据的传输通常使用二进制编码。

在某些情况下,为了确保数据的完整性和准确性,可以使用二进制反码进行校验。

发送方可以将原始数据的二进制反码添加到数据包中,接收方在接收到数据包后可以通过计算数据的二进制反码来验证数据的正确性。

3. 错误检测和纠正二进制反码也可以用于错误检测和纠正。

通过计算数据的二进制反码,可以检测数据在传输过程中是否发生了错误。

如果接收到的数据的二进制反码与发送方计算得到的二进制反码不一致,那么就说明数据在传输过程中发生了错误。

4. 存储空间优化在某些情况下,使用二进制反码可以优化存储空间的使用。

例如,在存储音频或视频数据时,可以使用二进制反码来表示幅度较小的信号,从而节省存储空间。

五、总结二进制反码是一种用于表示数字的编码方式,它在计算机科学和电子工程中有广泛的应用。

本文介绍了十进制数15的二进制表示和八位二进制反码表示,并探讨了二进制反码在补码表示、数据传输、错误检测和纠正以及存储空间优化等方面的应用。

通过了解和应用二进制反码,我们可以更好地理解和使用计算机科学和电子工程领域的相关知识。

参考文献无。

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

〈〈人工智能〉〉题目:15数码问题实验1:要求:采用广度优先算法解决15数码问题,输出扩展结点,步数和最终结果算法描述:广度优先搜索,即BFS(Breadth First Search),常常深度优先并列提及。

这是一种相当常用的图算法,其特点是:每次搜索指定点,并将其所有未访问过的近邻加入搜索队列(而深度优先搜索则是栈),循环搜索过程直到队列为空。

广度优先搜索算法的基本思想:从初始状态出发,按照给定的结点产生式规则(算符、结点扩展规则)生产第一层结点,每生成一个结点就检查是不是目标结点,如果是目标结点就搜索结束,如果不是目标结点并且前面没出现过就保存该结点(入队列);再用产生式规则将所有第一层的结点依次扩展,得到第二层结点,同时检查是否为目标结点,是目标搜索停止,不是并且没出现过保存(入队);再把第二层的结点按产生规则扩展生产第三层结点,直至找到目标或所有的状态找完但找不到目标(队列空)。

特点:先生成深度为1的所有结点,再生产深度为2的所有结点,依次类推。

先横向,再纵向。

这种方法找到目标,需要的步数一定最少。

程序算法流程图:描述:(1).把起始结点放到OPEN表中。

(2).如果OPEN表是个空表,则没有解,失败退出;否则继续。

(3).把第一个结点从OPEN表中移出,并把它放入CLOSE表的扩展节点表中。

(4).扩展结点N。

如果没有后继结点,则转向步骤(2)。

(5).把N的所有后继结点放到OPEN表的末端,并提供从这些后继结点回到N的指针。

(6).如果N的任意个后继结点是个目标结点,则找到一个解答,成功退出;否则转向步骤(2).流程图:输入:初始态int A[N][N]={{1,2,3,4},{5,10,6,8},{0,9,7,12},{13,14,11,15}};目标状态:int B[N][N]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};输出截图:由于输出的路径节点很多这里只是显示最终结果和步数。

实验2:要求:采用深度优先算法实现15数码问题。

算法描述:设x是当前被访问顶点,在对x做过访问标记后,选择一条从x出发的未检测过的边(x,y)。

若发现顶点y已访问过,则重新选择另一条从x出发的未检测过的边,否则沿边(x,y)到达未曾访问过的y,对y访问并将其标记为已访问过;然后从y开始搜索,直到搜索完从y出发的所有路径,即访问完所有从y出发可达的顶点之后,才回溯到顶点x,并且再选择一条从x出发的未检测过的边。

上述过程直至从x出发的所有边都已检测过为止。

此时,若x不是源点,则回溯到在x之前被访问过的顶点;否则图中所有和源点有路径相通的顶点(即从源点可达的所有顶点)都已被访问过,若图G是连通图,则遍历过程结束,否则继续选择一个尚未被访问的顶点作为新源点,进行新的搜索过程。

流程图:描述:(1).把起始结点放到OPEN表中。

如果此结点为一目标结点,则得到一个解。

(2).如果OPEN表是个空表,则没有解,失败退出;否则继续。

(3).把第一个结点从OPEN表中移出,并把它放入CLOSE表中。

(4).如果结点N的深度等于最大深度,则转向步骤(2)。

(5).扩展结点N,产生其全部后裔,并把它们放入OPEN表的前头。

如果没有后裔,则转向步骤(2)。

(6).如果N的任意个后继结点是个目标结点,则找到一个解答,成功退出;否则转向步骤(2).流程图:输入:初始态int A[N][N]={{1,2,3,4},{5,10,6,8},{0,9,7,12},{13,14,11,15}};目标状态:int B[N][N]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};输出截图:由于输出的路径节点很多这里只是显示最终结果和步数实验3:要求:采用启发式的A星算法实现15数码问题。

算法描述:启发式搜索算法A,一般简称为A算法,是一种典型的启发式搜索算法。

其基本思想是:定义一个评价函数f,对当前的搜索状态进行评估,找出一个最有希望的节点来扩展。

评价函数的形式如下:f(n)=g(n)+h(n)其中n是被评价的节点。

f(n)、g(n)和h(n)各自表述什么含义呢?我们先来定义下面几个函数的含义,它们与f(n)、g(n)和h(n)的差别是都带有一个"*"号。

g*(n):表示从初始节点s到节点n的最短路径的耗散值;h*(n):表示从节点n到目标节点g的最短路径的耗散值;f*(n)=g*(n)+h*(n):表示从初始节点s经过节点n到目标节点g的最短路径的耗散值。

而f(n)、g(n)和h(n)则分别表示是对f*(n)、g*(n)和h*(n)三个函数值的的估计值。

是一种预测。

A算法就是利用这种预测,来达到有效搜索的目的的。

它每次按照f(n)值的大小对OPEN表中的元素进行排序,f值小的节点放在前面,而f值大的节点则被放在OPEN表的后面,这样每次扩展节点时,都是选择当前f值最小的节点来优先扩展。

流程图:描述:(1).把起始结点放到OPEN表中。

计算F(S),并把其值与结点S联系起来。

(2).如果OPEN表是个空表,则没有解,失败退出;否则继续。

(3).从OPEN表中选择一个F值最小的结点I。

如果有几个结点合格,当其中有一个为目标结点时,则选择此目标结点,否则就选择其中任一个结点为结点I。

(4).把结点I从OPEN表中移出,并把它放入CLOSE的扩展结点表中。

(5).如果I是目标结点,则成功退出,求得一个解。

(6).扩展结点I,生成其全部后继结点。

对于I的每一个后继结点J:(a).计算F(J).(b).如果J既不再OPEN表中,也不再CLOSE表中,则用估价函数F把它添入OPEN表中。

从J加一指向其父辈结点I的指针,以便一旦找到目标结点时记住一个解答捷径。

(c).如果J已在OPEN表或CLOSE表上,则比较刚刚对J计算过的F值和前面计算过的该结点在表中的F值。

如果新的F值较小,则(i).以此新值代替旧值。

(ii).从J指向I,而不是指向它的父辈结点。

(iii).如果结点J在CLOSE表中,则把它移回OPEN表中。

(7).转向(2),即GOTO(2)流程图:输入:初始态int A[N][N]={{1,2,3,4},{5,10,6,8},{0,9,7,12},{13,14,11,15}};目标状态:int B[N][N]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};输出截图:6走完成,逆序输出。

各源代码见附件。

附件:(源程序代码)1 广度优先算法:#include <stdlib.h>#include <string.h>#include <stdio.h>#include<iostream.h>#define N 4typedef struct QNode{int data[N][N];int ancent; //标记方向左上下右分别为 1234 5为可以任意方向int x;int y;struct QNode *next;struct QNode *prior;}QNode, *QueuePtr;typedef struct{QueuePtr head;QueuePtr rear;}LinkQueue;int A[N][N]={{1,2,3,4},{5,10,6,8},{0,9,7,12},{13,14,11,15}};int B[N][N]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};int n=0;//记录步数int x,y;bool check(){//判断是否有路径,根据初始态和目标态的秩序,若不同为奇数或同为偶数,则无路径int temp=A[x][y];int i,j,sum2 = 0,sum1 = 0;int a[N*N],b[N*N];for(i=0;i<N;i++){for(j=0;j<N;j++){a[i*N+j]=A[i][j];}}for(i=0;i<N;i++){for(j=0;j<N;j++){b[i*N+j]=B[i][j];}}for(i=0;i<N*N-1;i++){for(j=i+1;j<N*N;j++){if(a[i]!=temp&&a[j]!=temp&&a[i]>a[j]) sum1++;}}for(i=0;i<N*N-1;i++){for(j=i+1;j<N*N;j++){if(b[i]!=temp&&b[j]!=temp&&b[i]>b[j]) sum2++;}}if((sum1%2==0&&sum2%2==1)||(sum1%2==1&&sum2%2==0)){ return false;}return true;}bool begin_opint(){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++){if(A[i][j]==0){x=i;y=j;return true;}}}return false;}bool compare(int a[N][N]){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++){if(a[i][j]!=B[i][j])return false;}}return true;}bool moveleft(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(y==0)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x][y-1];(*b)->data[x][y-1]=k;(*b)->x=x;(*b)->y=y-1;return true;}bool moveup(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(x==0)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x-1][y];(*b)->data[x-1][y]=k;(*b)->x=x-1;(*b)->y=y;return true;}bool movedown(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(x==N-1)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x+1][y];(*b)->data[x+1][y]=k;(*b)->x=x+1;(*b)->y=y;return true;}bool moveright(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(y==N-1)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x][y+1];(*b)->data[x][y+1]=k;(*b)->x=x;(*b)->y=y+1;return true;}bool copy(QueuePtr *a){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++)(*a)->data[i][j]=A[i][j];}return true;}void output(int a[N][N]){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++){printf(" %d",a[i][j]);}printf("\n");}printf("\n");}void main(){QueuePtr closed,p,q;LinkQueue open;/*if(!check()){printf("no answer!!\n"); //no answerexit(0);}*/if(!begin_opint()){printf("no 0 opint!!\n"); //确定0点exit(0);}open.head=open.rear=(QueuePtr)malloc(sizeof(QNode));//头结点open.rear->next=open.head->next=NULL;open.head->prior=open.head->prior=NULL;closed=(QueuePtr)malloc(sizeof(QNode));//头结点closed->next=NULL;closed->prior=NULL;p=(QueuePtr)malloc(sizeof(QNode));//S0进open表copy(&p);p->x=x;p->y=y;p->ancent=5;p->prior=NULL;p->next=open.head->next;open.head->next=p;open.rear=open.head; //open表的尾结点暂时设置为头结点while(open.head->next!=NULL){q=open.head->next; //open进closedopen.head->next=q->next; //移除open表头结点q->next=closed->next; //插入closed表的表头closed->next=q;n++;output(q->data);if(compare(q->data)){printf("ok!\n");printf("steps is %d\n",n);break;}//将后继结点放入open表中switch(closed->next->ancent){case 1: p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从右来if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=1;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=2;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(movedown(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=3;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);break;case 2:p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从下来if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=1;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=2;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveright(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=4;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);break;case 3:p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从上来if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=1;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(movedown(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=3;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveright(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=4;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);break;case 4:p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从左边来if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=2;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(movedown(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=3;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveright(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=4;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);break;default:p=(QueuePtr)malloc(sizeof(QNode));//初始情况if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=1;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=2;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(movedown(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=3;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveright(closed->next->data,&p,closed->next->x,closed->next->y)){p->prior=closed->next;p->ancent=4;p->next=open.rear->next;open.rear->next=p;open.rear=p;}else free(p);break;}}}2 深度优先算法:#include <stdlib.h>#include <string.h>#include <stdio.h>#include<iostream.h>#define N 4#define DEEP 10typedef struct QNode{int data[N][N];int ancent; //标记方向左上右下分别为 1234 5为可以任意方向int x;int y;int deep;struct QNode *next;}QNode, *QueuePtr;typedef struct{QueuePtr head;}LinkQueue;int A[N][N]={{1,2,3,4},{5,10,6,8},{0,9,7,12},{13,14,11,15}};int B[N][N]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};int n=0;//记录步数int x,y;bool check(){//判断是否有路径,根据初始态和目标态的秩序,若不同为奇数或同为偶数,则无路径int temp=A[x][y];int i,j,sum2 = 0,sum1 = 0;int a[N*N],b[N*N];for(i=0;i<N;i++){for(j=0;j<N;j++){a[i*N+j]=A[i][j];}}for(i=0;i<N;i++){for(j=0;j<N;j++){b[i*N+j]=B[i][j];}}for(i=0;i<N*N-1;i++){for(j=i+1;j<N*N;j++){if(a[i]!=temp&&a[j]!=temp&&a[i]>a[j]) sum1++;}}for(i=0;i<N*N-1;i++){for(j=i+1;j<N*N;j++){if(b[i]!=temp&&b[j]!=temp&&b[i]>b[j]) sum2++;}if((sum1%2==0&&sum2%2==1)||(sum1%2==1&&sum2%2==0)){ return false;}return true;}bool begin_opint(){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++){if(A[i][j]==0){x=i;y=j;return true;}}}return false;}bool compare(int a[N][N]){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++){if(a[i][j]!=B[i][j])return false;}}return true;}bool moveleft(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(y==0)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x][y-1];(*b)->data[x][y-1]=k;(*b)->x=x;(*b)->y=y-1;return true;}bool moveup(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(x==0)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x-1][y];(*b)->data[x-1][y]=k;(*b)->x=x-1;(*b)->y=y;return true;}bool movedown(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(x==N-1)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x+1][y];(*b)->data[x+1][y]=k;(*b)->x=x+1;(*b)->y=y;return true;}bool moveright(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(y==N-1)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x][y+1];(*b)->data[x][y+1]=k;(*b)->x=x;(*b)->y=y+1;return true;}bool copy(QueuePtr *a){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++)(*a)->data[i][j]=A[i][j];}return true;}void output(int a[N][N]){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++){printf(" %d",a[i][j]);}printf("\n");}printf("\n");}void main(){QueuePtr closed,p,q;LinkQueue open;/*if(!check()){printf("no answer!!\n"); //no answerexit(0);}*/if(!begin_opint()){printf("no 0 opint!!\n"); //确定0点exit(0);}open.head=(QueuePtr)malloc(sizeof(QNode));//头结点open.head->next=NULL;closed=(QueuePtr)malloc(sizeof(QNode));//头结点closed->next=NULL;p=(QueuePtr)malloc(sizeof(QNode));//S0进open表copy(&p);p->x=x;p->y=y;p->ancent=5;p->deep=0; //s0的深度为0p->next=open.head->next;open.head->next=p;while(open.head->next!=NULL){q=open.head->next; //open进closedopen.head->next=q->next; //移除open表头结点q->next=closed->next; //插入closed表的表头closed->next=q;if(q->deep<DEEP){n++;output(q->data);if(compare(q->data)){printf("ok!\n");printf("steps is %d\n",n);exit(0);}//将后继结点放入open表中switch(closed->next->ancent){ //左上右下 1234 case 1: p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从右来if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=1;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=2;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(movedown(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=4;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);break;case 2:p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从下来if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=1;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=2;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveright(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=3;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);break;case 3:p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从左来if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=2;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveright(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=3;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(movedown(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=4;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);break;case 4:p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从上边来if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=1;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveright(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=3;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(movedown(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=4;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);break;default:p=(QueuePtr)malloc(sizeof(QNode));//初始情况if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=1;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=2;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveright(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=3;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(movedown(closed->next->data,&p,closed->next->x,closed->next->y)){p->ancent=4;p->deep=closed->next->deep+1;p->next=open.head->next;open.head->next=p;}else free(p);break;}}}printf("over deep!!\n");}3 A*算法:#include <stdlib.h>#include <string.h>#include <stdio.h>#include<iostream.h>#define N 4typedef struct QNode{int data[N][N];int ancent; //标记方向左上右下分别为 1234 5为可以任意方向int x;int y;int gone; //是否遍历该节点,0未遍历,1遍历过int value; //和目标的状态差=不在位将牌距离和+深度int deep;struct QNode *father; //存放前一节点在"store"数组中的位置struct QNode *next;}QNode, *QueuePtr;typedef struct{QueuePtr head;QueuePtr rear;}LinkQueue;int A[N][N]={{1,2,3,4},{5,10,6,8},{0,9,7,12},{13,14,11,15}};int B[N][N]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};int x,y;QueuePtr min;//存放最小的结点bool check(){//判断是否有路径,根据初始态和目标态的秩序,若不同为奇数或同为偶数,则无路径int temp=A[x][y];int i,j,sum2 = 0,sum1 = 0;int a[N*N],b[N*N];for(i=0;i<N;i++){for(j=0;j<N;j++){a[i*N+j]=A[i][j];}}for(i=0;i<N;i++){for(j=0;j<N;j++){b[i*N+j]=B[i][j];}}for(i=0;i<N*N-1;i++){for(j=i+1;j<N*N;j++){if(a[i]!=temp&&a[j]!=temp&&a[i]>a[j]) sum1++;}}for(i=0;i<N*N-1;i++){for(j=i+1;j<N*N;j++){if(b[i]!=temp&&b[j]!=temp&&b[i]>b[j]) sum2++;}}if((sum1%2==0&&sum2%2==1)||(sum1%2==1&&sum2%2==0)){ return false;}return true;}bool begin_opint(){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++){if(A[i][j]==0){x=i;y=j;return true;}}}return false;}bool compare(int a[N][N]){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++){if(a[i][j]!=B[i][j])return false;}}return true;}bool moveleft(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(y==0)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x][y-1];(*b)->data[x][y-1]=k;(*b)->x=x;(*b)->y=y-1;return true;}bool moveup(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(x==0)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x-1][y];(*b)->data[x-1][y]=k;(*b)->x=x-1;(*b)->y=y;return true;}bool movedown(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(x==N-1)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x+1][y];(*b)->data[x+1][y]=k;(*b)->x=x+1;(*b)->y=y;return true;}bool moveright(int a[N][N],QueuePtr *b,int x,int y){ int k,i,j;if(y==N-1)return false;for(i=0;i<N;i++){for(j=0;j<N;j++)(*b)->data[i][j]=a[i][j];}k=(*b)->data[x][y];(*b)->data[x][y]=(*b)->data[x][y+1];(*b)->data[x][y+1]=k;(*b)->x=x;(*b)->y=y+1;return true;}bool copy(QueuePtr *a){int i,j;for(i=0;i<N;i++){for(j=0;j<N;j++)(*a)->data[i][j]=A[i][j];}return true;}void output(QueuePtr *p){int i,j;long int n=0;for(;(*p)->father!=NULL;(*p)=(*p)->father,n++){ for(i=0;i<N;i++){for(j=0;j<N;j++){printf(" %d",(*p)->data[i][j]);}printf("\n");}printf("\n");}printf("step is %d\n",n-1);}int getvalue(QueuePtr *p){int count=0;//保存距离bool test=true;//若已找到一个位置的值则继续找下一个//计算不在位的距离和for(int i=0;i<N;i++){for(int j=0;j<N;j++){test=true;for(int k=0;k<N;k++){for(int l=0;l<N;l++){if((i!=(*p)->x||j!=(*p)->y)&&(*p)->data[i][j]==B[k][l]){count=count+abs(i-k)+abs(j-l);test=false;}if(test==false) break;}if(test==false) break;}}}count=count+(*p)->deep;//加上深度值return count;}void main(){QueuePtr closed,p,q;LinkQueue open;if(!begin_opint()){printf("no 0 opint!!\n"); //确定0点exit(0);}/*if(!check()){printf("no answer!!\n"); //确定是否有解exit(0);}*/open.head=open.rear=(QueuePtr)malloc(sizeof(QNode));//头结点open.head->father=NULL;open.rear->next=open.head->next=NULL;closed=(QueuePtr)malloc(sizeof(QNode));//头结点closed->next=NULL;closed->father=NULL;p=(QueuePtr)malloc(sizeof(QNode));//S0进open表copy(&p);p->x=x;p->y=y;p->ancent=5;p->deep=0; //s0的深度为0p->gone=0;p->father=open.head;p->value=getvalue(&p); //p->next=open.head->next;open.head->next=p;open.rear=open.head;//min=p; //初始为s0结点if(compare(p->data)){output(&p);exit(0);}while(open.head->next!=NULL){/*q=open.head->next; //open进closedopen.head->next=q->next; //移除open表头结点q->next=closed->next; //插入closed表的表头closed->next=q;*///寻找最小状态for(min=q=open.head->next;q!=NULL;q=q->next){if(q->value<=min->value&&q->gone==0){min=q;break;}}min->gone=1;//改最小状态已遍历min->father->next=min->next;//在open表中删除找到的最小态min->next=closed->next; //插入closed表的表头//min->father=closed; //?closed->next=min;//空格向4个方向移动switch(closed->next->ancent){case 1: p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从右来if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->father=closed->next;p->ancent=1;p->gone=0;p->deep=min->deep+1;p->value=getvalue(&p);p->next=open.rear->next;open.rear->next=p;open.rear=p;//比较输出结果if(compare(p->data)){output(&p);exit(0);}}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->father=closed->next;p->ancent=2;p->gone=0;p->deep=min->deep+1;p->value=getvalue(&p);p->next=open.rear->next;open.rear->next=p;open.rear=p;//比较输出结果if(compare(p->data)){output(&p);exit(0);}}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(movedown(closed->next->data,&p,closed->next->x,closed->next->y)){p->father=closed->next;p->ancent=3;p->gone=0;p->deep=min->deep+1;p->value=getvalue(&p);p->next=open.rear->next;open.rear->next=p;open.rear=p;//比较输出结果if(compare(p->data)){output(&p);exit(0);}}else free(p);break;case 2:p=(QueuePtr)malloc(sizeof(QNode));//祖先结点从下来if(moveleft(closed->next->data,&p,closed->next->x,closed->next->y)){p->father=closed->next;p->ancent=1;p->gone=0;p->deep=min->deep+1;p->value=getvalue(&p);p->next=open.rear->next;open.rear->next=p;open.rear=p;//比较输出结果if(compare(p->data)){output(&p);exit(0);}}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveup(closed->next->data,&p,closed->next->x,closed->next->y)){p->father=closed->next;p->ancent=2;p->gone=0;p->deep=min->deep+1;p->value=getvalue(&p);p->next=open.rear->next;open.rear->next=p;open.rear=p;//比较输出结果if(compare(p->data)){output(&p);exit(0);}}else free(p);p=(QueuePtr)malloc(sizeof(QNode));//if(moveright(closed->next->data,&p,closed->next->x,closed->next->y)){p->father=closed->next;。

相关文档
最新文档