八数码(BFS)

摘要:
多亏了LJ大牛,才降到了400ms左右!=rev_num%2)printf;这里的剪枝不太理解,总是把可解的状态也剪掉了*/printf;printf;return0;}voidread{inti;charch[5];for{scanf;if(*s).a[i]=0;else(*s).a[i]=ch[0]-'0';}}intbfs{intfront,rear;intnx,ny,x,y;inti,code_t,code_nt;statet,nt;memset;memset;front=1;rear=2;Q[front]=start;dis[]=0;while{t=Q[front++];code_t=code;ifreturndis[code_t];for(i=0;t.a[i]!=0&&j˂9;++j);returnabs+abs;}此题已做,人生更加完整了,接下来几天打算试试别的方法。

参考白书的方法,将每一个状态映射到一个9位整数,然后再映射到它在所有状态中的大小位置(编码)来减少内存使用;

按照 POJ eight这道题的输入形式写的(对空格的处理参考了Staigner大牛的做法:用scanf一个字符串来读取);

输入包括初始状态和目标状态,输出为最短距离,如果无解,输出 -1;

逆序的剪枝比较难理解:当前状态逆序数+已走步数与目标态逆序数同奇偶则有解,有解状态不会扩展出无解状态,反之也成立,初始状态的逆序数+初始态与目标态之间空格的Manhattan距离与目标态同奇偶择有解,反之无解;

LJ 大牛提出了另一种剪枝的方法:将目标态中任意非零数互换位置得到的状态是无解状态可以达到的目标态,因此在搜索时,扩展到这些目标态表明当前状态无解;

BFS的标记写在了出队时导致了运行速度过慢(一个31步的数据跑了1s),我一直都是这样写BFS的……多亏了LJ大牛,才降到了400ms左右!

# include <stdio.h># include <mem.h># include <time.h># include <math.h>
# define N 362880+10
typedef struct{
   char a[9];
}state;

int fact[9];
charvis[N];
intdis[N];
state Q[N];

const int d[4][2] = {{-1,0}, {0,1}, {1,0}, {0,-1}};

void read(state*s);
intequal(state s1, state s2);
int compu_fact(void);
intcode(state s);
intrev_num(state s);
intbfs(state start, state goal);
intmanh_dis(state s1, state s2);

intmain()
{
    inti, j;
    state start, goal;
    
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    
    compu_fact();

    read(&start);
    read(&goal);   
   /*if ((rev_num(start)+manh_dis(start, goal))%2 != rev_num(goal)%2) printf("-1\n"); 
这里的剪枝不太理解,总是把可解的状态也剪掉了
*/printf("%d\n", bfs(start, goal)); printf("time used %.3lfs.\n", (double)clock()/CLOCKS_PER_SEC); return 0; } void read(state*s) { inti; char ch[5]; for (i = 0; i < 9; ++i) { scanf("%s", ch); if (ch[0] == 'x') (*s).a[i] = 0; else (*s).a[i] = ch[0] - '0'; } } intbfs(state start, state goal) { intfront, rear; intnx, ny, x, y; inti, code_t, code_nt; state t, nt; memset(vis, 0, sizeof(vis)); memset(dis, -1, sizeof(dis)); front = 1; rear = 2; Q[front] =start; dis[(code(start))] = 0; while (front <rear) { t = Q[front++]; code_t =code(t); if (equal(t, goal)) returndis[code_t]; for (i = 0; t.a[i]!=0 && i < 9; ++i) ; x = i / 3; y = i % 3; for (i = 0; i < 4; ++i) { nx = x + d[i][0]; ny = y + d[i][1]; if (nx>=0 && nx<3 && ny>=0 && ny<3) { nt =t; nt.a[3*x+y] = t.a[nx*3+ny]; nt.a[nx*3+ny] = 0; code_nt =code(nt); if (!vis[code_nt]) { vis[code_nt] = 1; Q[rear++] =nt; dis[code_nt] = dis[code_t] + 1; } } } } return -1; } intcode(state s) { inti, j, cnt, ret; ret = 0; for (i = 0; i < 9; ++i) { cnt = 0; for (j = i+1; j < 9; ++j) if (s.a[j] < s.a[i]) ++cnt; ret += fact[8-i]*cnt; } returnret; } int compu_fact(void) { inti; fact[0] = 1; for (i = 1; i < 9; ++i) fact[i] = fact[i-1]*i; } intequal(state s1, state s2) { inti; for (i = 0; i < 9; ++i) if (s1.a[i] != s2.a[i]) return 0; return 1; } intrev_num(state s) { inti, j, ret; ret = 0; for (i = 0; i < 9; ++i) for (j = i+1; j < 9; ++j) if (s.a[i] > s.a[j]) ++ret; returnret; } intmanh_dis(state s1, state s2) { inti, j; for (i = 0; s1.a[i]!=0 && i<9; ++i) ; for (j = 0; s1.a[j]!=0 && j<9; ++j) ; return abs(i/3 - j/3) + abs(i%3 - j%3); }

此题已做,人生更加完整了,接下来几天打算试试别的方法(学学A*等启发式方法)。

免责声明:文章转载自《八数码(BFS)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇kube-dns和coreDNS的使用Python之并发编程(二)进程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

【转载】SecureCRT配色推荐和永久设置

2.配置文件夹和其他颜色选项==“全局选项==”终端==“外观==”ANSI颜色单击第二行中的第五个色块以修改文件夹颜色:对第二个色块执行相同的操作以修改压缩包和jar包的颜色:如果设置后文件夹和其他的颜色无效,您可以对第二行中设置背景色和字体颜色的颜色块执行相同的操作!...

开源BI分析工具Metabase配置与完全使用手册

文章目录简介安装初始配置数据分析简单查询创建场景创建集合和仪表盘自定义查询原生查询sql变量动态sql片段管理员操作添加数据库连接oracle成员管理邀请新成员权限配置数据权限文件夹权限邮箱配置定时任务简介Metabase是一个免费的BI分析工具,可以帮助你把数据库中的数据更好的呈现给更多人,通过建立一个”查询“来提炼数据,再以图形化的方式做展示。上手简单,...

MarkDown技巧:两种方式实现页内跳转

MarkDown技术:有两种方法可以跳转到页面上的电子邮件地址:JohnTsai.Work@gmail.com,欢迎交流讨论。我喜欢MarkDown简单直观的写作风格。...

vue中获取客户端IP地址

ice||!ice.candidate||!...

Cesium深入浅出之可视域分析【转】

吸引人的视觉领域分析功能终于到来了!但没有办法。铯不支持自定义光源。没有它,我们就无法实现可视化领域分析。MaximumDistanceNumber5000.0生成级联阴影的最大距离。黑暗数字0.3阴影的黑暗。Frustum也称为平截头体,是相机的视觉表示。原始笛卡尔3圆锥体的起点。让我们改变想法。由于ShadowMap的构建需要一个摄像头,我们可以直接使用...

使用代理软件之后其他软件不能联网的解决方法

可能是代理软件打开后,代理端口被自动修改,但我们没有正常关闭代理软件。代理端口没有在此代理模式下切换回来,因此我们仍然使用全局代理,但没有打开代理软件。此时,网络无法正常连接。此时,其他软件可以正常使用,但使用全局代理的速度非常慢。除非您需要FQ,否则不建议对通用软件使用全局代理。...