做了好几天,几个小错误,没耐心都没调试出来..

A* 最小堆 hash表 还是超时..诶

告一段落...

/*
分析:
A*搜索的状态包含了布局和在搜索树中的深度.
因为在优先队列的优先级是f,所以无法实现布局的二分查找.但是在open和close表中又要查找布局.不可行..
通过hash表来记录已经搜索过的布局的最小f,那么不需要在堆中查找,如果f较大,不入队列,也能保证最短步数.
按照从上到下,从左到右的顺序,八数码就是123456780,9个数字的排列是9!.
*/#include <iostream>
#include <cmath>
#include <stack>
using namespace std;const int MAX = 1 << 20;
int step;
const int EndPos[9][2] = {{2, 2}, {0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}, {2, 0}, {2, 1}};
const int hashFac[9] = {1, 2, 6, 24, 120, 720, 5040, 40320};
int hash_table[MAX];
int heap_last;//堆中最后一个元素的下标(可插入位置-1)
const int dir[4][2] = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}};//r,u,l,d
const int EndBoard[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 0};struct Status
{int board[3][3];int r, c;int d;//移动方向int g,h;Status *father;
}start, End, Queue[MAX], Step[MAX];;//用堆来实现的优先队列,第一个元素的小标是1int HFun(const Status &s)
{int tile, cnt = 0;for(int r = 0; r < 3; r++)for(int c = 0; c < 3; c++){tile = s.board[r][c];if(0 != tile)cnt += abs(EndPos[tile][0] - r) + abs(EndPos[tile][1] - c);}return cnt;
}
bool operator<(const Status &s1, const Status &s2)
{return ((s1.g + s1.h) < (s2.g + s2.h));//这里刚开始的时候把h也写成了g..
}int HashVal(const Status &s)//全排列hash函数,不会冲突
{int i,j,k = 0,array[9];for(i = 0; i < 3; i++)for(j = 0; j < 3; j++)array[k++] = s.board[i][j];int cnt = 0, res = 0;for(i = 0; i < 9; i++){cnt = 0;for(j = 0; j < i; j++)if(array[j] > array[i])cnt++;res += cnt * hashFac[i];}       return res;
}bool Empty()
{return 0 == heap_last;
}//向下维护小顶堆
void down_min_heap()
{Status s = Queue[1];int i,j;for(i = 1, j = i<<1; j <= heap_last; j = j << 1){if(j + 1 <= heap_last && Queue[j + 1] < Queue[j])//较小孩子节点的下标j++;if(Queue[j] < s){Queue[i] = Queue[j];//元素上移i = j;}elsebreak;}Queue[i] = s;
}Status Pop()
{Status s = Queue[1];Queue[1] = Queue[heap_last--];down_min_heap();return s;
}/*
向上维护小顶堆
父亲结点必定小于另外一个孩子结点
所以如果该结点小于父亲结点,那么也小于另外一个孩子结点,直接往上移动就好
否则已经满足小顶堆特性
*/
void up_min_heap()
{int i,j;Status s = Queue[heap_last];for(j = heap_last, i = j>>1; i >= 1; i = i >> 1){if(s < Queue[i]){Queue[j] = Queue[i];j = i;}elsebreak;}Queue[j] = s;
}void Push(const Status &s)
{Queue[++heap_last] = s;up_min_heap();
}void Trace();
bool Astar()
{memset(hash_table, 0, sizeof(hash_table));int r, c, nr, nc, tile, f, hashVal;start.g = 0;start.h = HFun(start);hash_table[HashVal(start)] = start.g + start.h;Push(start);Status s, ns;while(!Empty()){s = Pop();Step[step++] = s;if(!memcmp(s.board, EndBoard, sizeof(EndBoard))){End.father = &s;Trace();return true;}r = s.r; c = s.c;for(int d = 0; d < 4; d++){if(abs(s.d - d) == 2){continue;}nr = r + dir[d][0]; nc = c + dir[d][1];if(nr < 0 || nr > 2 || nc < 0 || nc > 2)continue;ns = s;ns.d = d;tile = ns.board[nr][nc];ns.board[r][c] = tile;ns.board[nr][nc] = 0;ns.r = nr; ns.c = nc;//这里刚开始写成了c,结果调试的时候发现经常2个0..无限蛋疼!!!ns.g++;ns.h = HFun(ns);f = ns.g + ns.h;hashVal = HashVal(ns);if(hash_table[hashVal] < f)//未访问或者估价更小的状态{hash_table[hashVal] = f;ns.father = &Step[step - 1];Push(ns);}}//cout<<heap_last<<endl;}return false;
}void input()
{int tile;for(int r = 0; r < 3; r++)for(int c = 0; c < 3; c++){cin>>tile;if(cin.fail()){cin.clear();cin.ignore(1, ' ');start.r = r;start.c = c;start.board[r][c] = 0;}else{start.board[r][c] = tile;}/*if(!tile){start.r = r;start.c = c;}*/}start.d = 100;//第一次不定义方向
}bool Solveable()
{int i, j, array[9], k = 0, sum = 0;for(i = 0; i < 3; i++)for(j = 0; j < 3; j++)array[k++] = start.board[i][j];for(i = 8; i >= 0; i--)for(j = i - 1; j >= 0; j--)if(array[j] && array[j] < array[i])sum++;if(sum % 2 == 0)return true;elsereturn false;
}void Trace()
{stack<int> trace;Status *p = End.father;while(p){trace.push(p->d);p = p->father;}while(!trace.empty()){int d = trace.top();trace.pop();switch(d){case 0:cout<<'r';break;case 1:cout<<'u';break;case 2:cout<<'l';break;case 3:cout<<'d';break;}}cout<<endl;
}int main()
{//freopen("in.txt", "r", stdin);input();if(Solveable())Astar();elsecout<<"unsolvable"<<endl;return 0;
}

转载于:https://www.cnblogs.com/steady/archive/2011/01/21/1941733.html

pku 1077 Eight相关推荐

  1. hdu 1043 ,pku 1077 Eight ,八数码问题

    某位神牛曾说过,此题是涉及到人生完不完整的一道题.. Goodness大牛曾总结了 八数码的八重境界 : http://www.cnblogs.com/goodness/archive/2010/05 ...

  2. pku,zju题目分类

    哎呦喂,直接ctrl+A了.话说浙江大学的题还见过的呢.. 公告: [意见反馈][官方博客]   ural pku Zju 题目分类 收藏   感谢 mugu 的提供.... Ural Problem ...

  3. PAT甲级1077 Kuchiguse:[C++题解]字符串、最长公共后缀

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 读入n个字符串s[n],以s[0]为基础找公共后缀.枚举后缀的长度,内层循环遍历其他字符串,判断是否后缀相等. 使用子串的函数sub ...

  4. Follow My Logic 1048 PKU

    Follow My Logic http://acm.pku.edu.cn/JudgeOnline/problem?id=1048 确定由一个或多个输入.0个或多个与或门组成的逻辑电路 电路路径通过水 ...

  5. 1077篇!ICCV2019接收结果公布,你中了吗?(附7篇论文链接,含Oral)

    原文链接:1077篇!ICCV2019接收结果公布,你中了吗?(附7篇论文链接,含Oral) 点击加入**极市CV技术交流群**,交流更多人计算机视觉相关的技术干货 ICCV2019接收论文id查看链 ...

  6. 【记忆化搜索】【线性化DP】滑雪 (ssl 1202/luogu 1434/pku 1088)

    滑雪滑雪滑雪 ssl 1202 luogu 1434 pku 1088 题目大意: 有一个N*M的矩阵,每个位置都有一个数,可以从大的数走向小的数,问可走的路最长是多少 原题 Michael喜欢滑雪百 ...

  7. 信息学奥赛一本通 1077:统计满足条件的4位数 | OpenJudge NOI 1.5 26

    [题目链接] ybt 1077:统计满足条件的4位数 OpenJudge NOI 1.5 26:统计满足条件的4位数个数 [题目考点] 1. 分离整数的各位数字 对于数字a,a%10可以取到其个位,a ...

  8. 信息学奥赛一本通(1077:统计满足条件的4位数)

    1077:统计满足条件的4位数 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 32955     通过数: 22461 [题目描述] 给定若干个四位数,求出其中满 ...

  9. 细粒度图像分类_北大提出PKU FG-XMedia:细粒度跨媒体检索数据集和评测基准

    北京大学彭宇新教授团队建立了第一个包含 4 种媒体类型(图像.文本.视频和音频)的细粒度跨媒体检索公开数据集和评测基准 PKU FG-XMedia,并且提出了一种能够同时学习 4 种媒体统一表征的深度 ...

最新文章

  1. Git Fetch vs Pull:Git Fetch和Git Pull命令之间有什么区别?
  2. javascript调试_如何提高JavaScript调试技能
  3. opencv python BRIEF描述子
  4. anconda安装及opencv配置
  5. hdu 2047(递推)
  6. Spring AOP编程-aspectJ代理方式选择
  7. pythonpil安装教程_Python 3.6 -win64环境安装PIL模块的教程
  8. python怎么让py里面逐行运行_[python]开发环境bug(求助)
  9. 简练软考知识点整理-公邀竞单询其
  10. shiro 单点登录_Shiro权限管理框架(一):Shiro的基本使用
  11. 关于ajax跨域的问题
  12. 高通平台camera bring-up
  13. python-pycharm使用方法
  14. 单元格 编辑 获取_Excel批量导入图片,还能一键将图片固定到单元格!这是什么操作.........
  15. vue 判断设备是手机端还是pc端
  16. SSM框架实战详细教程(六)Spring MVC贯穿项目实战
  17. code vs 集成tfs_Microsoft强大团队(源代码)管理工具--TFS2010 与vs结合
  18. matlab显示串联矩阵的维度不一致,串联的矩阵的维度不一致。
  19. HANA 基础SQL和SQLScript
  20. 证明最小码距与纠检错图像_最小码距和检错纠错能力关系

热门文章

  1. java实现stack search_Java Stack search()用法及代码示例
  2. python 守护线程 join_Python多线程threading join和守护线程setDeamon原理详解
  3. python里面self_Python中的self详细解析
  4. 了解下Lua 环境安装
  5. 想从事单片机工作,C语言要达到什么水平?
  6. 单片机对于大学生难学吗?
  7. C语言必须会写的10道经典题(小白必看!)
  8. 荣耀3OS怎么升级鸿蒙系统,华为鸿蒙OS正式发布!教你如何升级
  9. python3里的pillow怎么安装_“python安装pillow教程“python3.4怎么安装pil
  10. logstash mysql eror_Logstash安装记录(报错com.mysql.jdbc.Driver not loaded的解决)