SOJ2061 8 puzzle
来源:互联网 发布:关联规则和als矩阵 编辑:程序博客网 时间:2024/06/05 16:31
人生中第一次写A*,贡献了4TLE+4RE+4WA才换来一个宝贵的AC。
有几个地方需要总结的。
1.一定要判断开始局面能否到达结束局面,用逆序数判断。否则A*算法将搜索完所有可能的状态,导致TLE。
2.hash函数要选择好,一开始我直接使用了stl::map来hash,很慢,也会导致TLE。用逆序数列来保存状态,可以保证最多有362880个状态。
3.在把子节点加入开列表中时,不能直接将它的hash值设为已访问,在开列表中可能有多个重复但g不同的节点,应在取出节点时设为已访问。否则会WA。
4.不必把局势表示成3*3的矩阵,一维矩阵就可以了,更快,上下左右可以用-3,+3,-1,+1来表示。
#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int d[4]={1,-1,3,-3};int ans,a[10],b[10],bb[10][2];bool vis[400000];int c[9]={1,1,2,6,24,120,720,5040,40320};void swap(int &a, int &b){ int t=a;a=b;b=t;}bool inside(int i,int j){ if (i+j<0 || i+j>=9) return 0; if (i%3==0 && j==-1) return 0; if (i%3==2 && j==1) return 0; return 1;}struct Node{ int num[10]; int f,g,h,hash; bool operator < (const Node &o) const {return f>o.f;} void geth() { h=0; for (int i=0;i<9;i++) if (num[i]) h+=abs(i/3-bb[num[i]][0])+abs(i%3-bb[num[i]][1]); } void gethash() { hash=0; int cnt=0,zero; for (int i=0;i<9;i++) { if (num[i]==0) {zero=i; continue;} int k=0; for (int j=0;j<i;j++) if (num[j]>num[i]) k++; hash+=k*c[cnt++]; } hash+=(8-zero)*c[8]; } void hehe() { gethash(); if (vis[hash]) return; geth(); f=g+h; }}t,tt;priority_queue<Node> Q;void Astar(){ while (!Q.empty()) Q.pop(); memset(vis,0,sizeof(vis)); for (int i=0;i<9;i++) t.num[i]=a[i]; t.g=0; t.hehe(); Q.push(t); while (!Q.empty()) { t=Q.top(); Q.pop(); if (vis[t.hash]) continue; vis[t.hash]=1; if (t.h==0) {ans=t.g; return;} int zero; for (int i=0;i<9;i++) if (t.num[i]==0) zero=i; for (int r=0;r<4;r++) { if (!inside(zero,d[r])) continue; tt=t; swap(tt.num[zero],tt.num[zero+d[r]]); tt.g=t.g+1; tt.hehe(); if (vis[tt.hash]) continue; Q.push(tt); } }}int main(){ int T,x; scanf("%d",&T); while (T--) { for (int i=0;i<9;i++) scanf("%d",&a[i]); for (int i=0;i<9;i++) scanf("%d",&b[i]); int inv=0; for (int i=0;i<9;i++) for (int j=0;j<i;j++) { if (a[i]&&a[j]&&a[i]<a[j]) inv++; if (b[i]&&b[j]&&b[i]<b[j]) inv++; } if (inv&1) { puts("-1"); continue; } for (int i=0;i<9;i++) { x=b[i]; bb[x][0]=i/3; bb[x][1]=i%3; } ans=-1; Astar(); printf("%d\n",ans); } return 0;}
- SOJ2061 8 puzzle
- 拼图游戏(8 puzzle)
- puzzle
- puzzle
- puzzle
- Puzzle
- Puzzle
- Puzzle
- puzzle
- 8 Puzzle/8 数码问题
- 8 puzzle with A* algorithm
- 8数码,8PUZZLE 问题 C++ 代码
- ACM--steps--4.3.8--Another Eight Puzzle
- usaco 4.4 Shuttle Puzzle 2010.8.8
- 8 Puzzle 算法原理和源码
- hdu 6048 Puzzle 思维(8数码问题
- Coursera Algorithm Week4 8-puzzle tricks
- Principle of Computing (Python)学习笔记(8) Fifteenth Puzzle
- excel中判断一个表中的某一列的数据在另一个表中的某一列中是否存在
- ldd for android
- windows 远程登录linux (ubuntu虚拟机)
- Python文件操作
- vim配置手册
- SOJ2061 8 puzzle
- 敢吃“活动”页面数据格式
- 【转】ArcGIS栅格数据的属性表受65536限制的问题
- 299 - Train Swapping
- Eclipse SVN忽略不需要的文件夹
- ArrayList的使用方法
- iOS通过iTunes search检测版本更新,并提示用户更新
- 嵌入式笔试题
- 根搜索算法