人工智能(梵塔问题)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
梵塔问题实验报告
实验目的
1. 熟悉和掌握问题规约法的原理、实质和规约过程
2. 理解规约图的表示方法
3. 熟悉并掌握递归解决问题的思想
实验原理
1. 利用问题规约法的原理进行问题的分析与描述
2. 利用递归思想进行问题的解决
实验条件
1. Window NT/xp/7及以上的操作系统
2. 内存在512M以上
3. CPU在奔腾II以上
实验内容
梵塔问题源于印度古老的一个传说。
相传开天辟地的神勃拉玛创造世界时在
印度北部的佛教圣地的圣庙里,安放了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,但每次只能搬一个,而且大的不能放在小的上面。
值班僧侣按照法则日夜不停地搬运,当搬运完成时世界将在一声霹雳中毁灭。
实验分析
我们假设把该任务交给一个僧人,为了方便叙述,将他编号为64。
僧人自然
会这样想:假如有另外一个僧人能有办法将63个盘子从一个座移到另一个座,那么问题就解决了,此时僧人64只需这样做:
1. 命令僧人63将63个盘子从A座移到C座
2. 自己将最底下的最大的一个盘子从A座移到C座
3. 再命令僧人63将63个盘子从B座移到C座
为了解决将63个盘子从A座移到B座的问题,僧人63又想:如果能再有一个僧人62能将62个盘子移动到另一座,我就能将63个盘子从A座移动到B座。
他是这样做的:
1. 命令僧人62将62个盘子从A移动到C
2. 自己将一个盘子从A座移动到B座
3. 再命令僧人62将62个盘子移到B座
再进行一次递归。
如此“层层下放”,直到后来找到第2个僧人,让他完成将2个盘子从一个座移到另一个座,进行到此,问题就解决了。
最后找到第1个僧人,让他完成将一个盘子从一个座移动到另一个座,至此,全部工作已经完成,该烦他问题得到解决。
实验步骤
⑴主程序流程图
主程序流程图
⑵梵塔求解流程图
#defi ne PANHOU 10 /*#define PANAMOUNT 19 盘子数 */ int PANAMOUNT; typedef int pans; typedef struct s_pillar {
int amount;
int x,y;
pans pan[ 20]; /*
}pillars;
pillars pillar[4]; /* int moveco un t=0; /*
void drawpillar(pillars p); void
in it(); /* void
drawmat(ehar *mat,int
matsize,int x,int y,int color); /* void drawpa n(pans p,i nt x,i nt y);
梵塔问题递归过程流程图 程序代码 #in elude
<stdio.h> #in elude
<graphics.h>
#in elude <time.h> #in elude <dos.h> #in elude
<math.h> #defi ne PAOGAO 190 /*
动画抛高,数值越小越高 */
存放每个盘的代号*/
三个台柱*/
移动计数*/
初始化函数*/
点陈汉字*/
void zimu(); /* void
drawpps(); /* void hanoi(); /*
void hanoi(int n,char
one,char two,char three); void sdelay(int delay_t); /* 函数申明 */ void finish();
/* 完成! */ void main(void) /* 主函数 */ {
printf("\n\tplease input n(n<=19): ");/*
输入要演示的盘子数 */
scanf("%d",&PANAMOUNT);
if(PANAMOUNT<1||PANAMOUNT>19) /* 越界的话 n 当 19 处理 */
PANAMOUNT=19 ;
init();
drawpps();
hanoi(PANAMOUNT,'a','b','c');
finish(); }
void init() /* 初始化函数 */
{
int gd=DETECT,gm ;
int i,n,color ;
clrscr();
initgraph(&gd,&gm,"c:\\tc");
cleardevice();
pillar[1].amount = PANAMOUNT; pillar[1].x = 105;
pillar[1].y = 405; for(i=1;i<=pillar[1].amount;i++) {
pillar[1].pan[i]=pillar[1].amount-i+1;
}
pillar[2].amount = 0; pillar[2].x = 320; pillar[2].y = 405;
pillar[3].amount = 0; pillar[3].x = 527; pillar[3].y = 405; setcolor(YELLOW); /* settextstyle(0,0,2);
显示字幕 */ 画装盘的台柱 */ 主算法 */ 柱座标记 */
outtextxy(105,418,"A");
outtextxy(320,418,"B");
outtextxy(527,418,"C");
setcolor(YELLOW); /* 画框*/
setlinestyle(SOLID_LINE,0,NORM_WIDTH);
line(0,0,0,479);
line(0,0,639,0);
line(639,0,639,479);
line(0,479,639,479);
line(0,PAOGAO-PANHOU-40,450,PAOGAO-PANHOU-40); /* 黄金线*/
settextstyle(0,0,1);
线上字*/ outtextxy(250,PAOGAO-PANHOU-50,"Press ANY Key to EXIT !"); /*
zimu();
}
void drawpillar(pillars p) /* 画柱*/
{
int x,y,mount;
x=p.x;
y=p.y;
mount=p.amount; setfillstyle(SOLID_FILL,BROWN); bar(x,(y-mount*PANHOU-
20),x+5,y);
bar(x-45,y,x+55,y+5);
}
void drawmat(char *mat,int matsize,int x,int y,int color)
/* 依次:字模指针、点阵大小、起始坐标(x,y) 、颜色*/
{int i,j,k,n;
n=(matsize-1)/8+1;
for(j=0;j<matsize;j++)
for(i=0;i<n;i++)
for(k=0;k<8;k++)
if(mat[j*n+i]&(0x80>>k)) /* 测试为1 的位则显示*/ putpixel(x+i*8+k,y+j,color);
}
void drawpan(pans p,int x,int y)
{
setfillstyle(SOLID_FILL,LIGHTGRAY); bar(x-(5+5*p),y-
PANHOU+1,x+(5+5*p),y); setlinestyle(SOLID_LINE,0,NORM_WIDTH);
setcolor(BLACK);
line(x-(5+5*p),y,x+(5+5*p),y);
line(x-(5+5*p),y+1,x+(5+5*p),y+1);
}
void clearpan(pans p,int x,int y)
setfillstyle(SOLID_FILL,BLACK); bar(x-(5+5*p),y-PANHOU,x+(5+5*p),y); }
void drawpps() /* 画装盘的台柱*/
{
pillars p;
int i,j;
int x,y,mount;
for(i=1;i<=3;i++)
{
p = pillar[i];
x = p.x;
y = p.y;
mount = p.amount;
drawpillar(p); /* 画台柱*/ for(j=1; j<=mount ;j++)
{
drawpan(p.pan[j],x,y-PANHOU*(j-1));
}
}
}
void hanoi(int n,char one,char two,char three)
{
void move(char x,char y); /* 声明*/ if(n==1)
{ move(one,three);
}
else
{ hanoi(n-1,one,three,two); move(one,three); hanoi(n-1,two,one,three);
}
}
void move(char x,char y)
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 1);
outtextxy(560,30+movecount*10,a);
outtextxy(580,30+movecount*10,"--->");
outtextxy(620,30+movecount*10,b);
setfillstyle(SOLID_FILL,BLACK);/* 涂黑_重画 */
bar(3,pillar[1].y-PANHOU*19-20,584,412);
drawpps(); /* 重画 */
action(data,pillar[ifrom],pillar[ito]);/*
pillar[ito].amount++; /* mountt =
pillar[ito].amount;/*
pillar[ito].pan[mountt] = data;
drawpps(); /* 重画 */ } void clearprocess() {
int i;
setfillstyle(SOLID_FILL,BLACK);
for(i=0;i<=16;i++)
{
bar(545,30+i*10,638,40+i*10);
sdelay(1); /* 动画延迟 n 个 (1/18.2) 秒*/ }
}
void clearprocess(); /*
void action(); /* int
ifrom,ito;
pans data; int
mountf,mountt;
申明函数 */ 申明移动动画函数 */ char a[1];
char b[1];
a[0]=x;a[1]='\0';
b[0]=y;b[1]='\0';
ifrom = x-96;
ito = y-96;
mountf = pillar[ifrom].amount; /*
mountt = pillar[ito].amount; data
= pillar[ifrom].pan[mountf];
pillar[ifrom].amount--; /*
数量
*/ 出栈 */ sdelay(6); /* 暂停屏幕 */
if(movecount>=15) clearprocess();/*
清除步骤提示 */ movecount = movecount%15+1; /* 模 20+1*/
setcolor(RED); /*
输出移动过程 */ 此处添加动画函数 */ 入栈 */ 刷新数量 */
整数 1 代表(1/18.2) 秒*/
void sdelay(int delay_t)
{
clock_t start_time ; start_time=clock();
while((clock()-start_time)<delay_t) ; /* 循环空语句*/
}
void action(pans pan,pillars fromp,pillars top) /* 移动动画*/
{
float x1,y1,x2,y2;
float p,q,a;
int x,y,temp; /* 整形变量用与当前帧*/
x1 = (float)(fromp.x);
y1 = (float)(fromp.y - fromp.amount*PANHOU -20);
/*PANHOU 为盘厚常数, 减20 处理,以便避开柱子*/ x2 = (float)(top.x);
y2 = (float)(top.y - top.amount*PANHOU);
q = -sqrt((y1-PAOGAO)/(y2-PAOGAO)); /* 此处注意产生增根*/ if(1-q) /* 除数不为0*/
{
a = (x1 - x2*q)/(1-q);
}else a = (x1+x2)/2.0;
p = (y2-PAOGAO)/(x2-a)/(x2-a);/* 除以平方*/
if(x1 <= x2)
{
for(x=floor(x1+0.5); x<floor(x2+0.5); x=x+ 7 )
{
if(kbhit()) exit(); /* 用户按ESC则退出*/
y =floor((p*(x-a)*(x-a)+PAOGAO)+0.5); drawpan(pan,x,y);
sdelay(1);
clearpan(pan,x,y);/* 清除轨迹*/
}
}else
{
for(x=floor(x1+0.5); x>floor(x2+0.5); x=x- 7 )
{
if(kbhit()) exit(); /* 用户按ESC则退出*/
y = floor((p*(x-a)*(x-a)+PAOGAO)+0.5);
drawpa n(pan, x,y);
sdelay(1);
clearpan(pan,x,y);/* 清除轨迹*/
}
}
}
void finish() /* 完成!*/
{
getch();
closegraph();
}
程序运行效果图
A*" Bi' C+1
A+J 3 C+J
2 B+J O A+J &4-1O
A+J BJ CV
A
阳1
A*1乐
C*J
A+J B*
2
个人实验小结
通过本次实验,我学会了熟悉并掌握问题规约法的原理、实质和规约过程,理解了规约图的表示方法,熟悉并掌握递归解决问题的思想。
使我的软件编程思维能力得到了很大的提升,使我的自身能力有了长足的进步。