博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 1043 Eight (A* + HASH + 康托展开)
阅读量:5731 次
发布时间:2019-06-18

本文共 6399 字,大约阅读时间需要 21 分钟。

Eight

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13956    Accepted Submission(s): 3957 Special Judge

Problem Description
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:
1  2  3  4  5  6  7  8  9 10 11 12 13 14 15  x
where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:
1  2  3  4     1  2  3  4     1  2  3  4     1  2  3  4  5  6  7  8     5  6  7  8     5  6  7  8     5  6  7  8  9  x 10 12     9 10  x 12     9 10 11 12     9 10 11 12 13 14 11 15    13 14 11 15    13 14  x 15    13 14 15  x             r->            d->            r->
The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.
Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three arrangement.
 
Input
You will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle
1  2  3 x  4  6 7  5  8
is described by this list:
1 2 3 x 4 6 7 5 8
 
Output
You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
 
Sample Input
2 3 4 1 5 x 7 6 8
 
Sample Output
ullddrurdllurdruldr
 
 
 
这题活生生搞了五天,为此学了A*和康托展开,虽然自己写出来了但还不是非常明白,有句话说“如果你真的懂了那么你就应该自己动手做一个”,看来我还没真的懂。
首先把每次矩阵的格局存结构里,然后对整个矩阵用康托展开来进行哈希,得到一个值,以此来判断此种情况是否出现过或是是否到达了终点,有一个很好的剪枝就是用奇偶逆序数来判断是否可解,因为最终情况的逆序数是0,而每次变换不会改变逆序数的奇偶,所以如果初始情况的逆序数是奇数的话就不可解。
不明白的地方是A*的估值函数为何不用f = g + h,而是要用h和g分别作为两个参数来比较,刚开始的时候我把两个参数的位置弄反了, T了一天。都是泪。
1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 using namespace std; 9 10 const int SIZE = 5; 11 const int GOAL = 46233; 12 const int HASH[] = { 40320,5040,720,120,24,6,2,1,1}; 13 const int UP_DATE[][2] = { { 0,-1},{ 0,1},{-1,0},{ 1,0}}; 14 int PATH[600000]; 15 int PRE[600000]; 16 struct Node 17 { 18 int map[SIZE][SIZE]; 19 int x,y; 20 int h,g; 21 int hash; 22 bool operator <(const Node a) const 23 { 24 return h != a.h ? h > a.h : g > a.g; 25 } 26 }; 27 28 bool solve_able(const Node & r); 29 bool check(const int,const int); 30 void cal_hash(Node & r); 31 void cal_h(Node & r); 32 void search(const Node & r); 33 void show(void); 34 int main(void) 35 { 36 Node first; 37 char s[50]; 38 39 while(gets(s)) 40 { 41 int k = 0; 42 memset(PRE,-1,sizeof(PRE)); 43 memset(PATH,-1,sizeof(PATH)); 44 for(int i = 1;i <= 3;i ++) 45 for(int j = 1;j <= 3;j ++) 46 { 47 if(s[k] >= '1' && s[k] <= '9') 48 first.map[i][j] = s[k] - '0'; 49 else if(s[k] == 'x') 50 { 51 first.map[i][j] = 0; 52 first.x = i; 53 first.y = j; 54 } 55 else 56 j --; 57 k ++; 58 } 59 if(!solve_able(first)) 60 { 61 printf("unsolvable\n"); 62 continue; 63 } 64 cal_hash(first); 65 if(first.hash == GOAL) 66 { 67 puts(""); 68 continue; 69 } 70 PATH[first.hash] = -2; 71 first.g = 0; 72 cal_h(first); 73 search(first); 74 } 75 76 return 0; 77 } 78 79 bool solve_able(const Node & r) 80 { 81 int sum = 0,count = 0; 82 int temp[10]; 83 84 for(int i = 1;i <= 3;i ++) 85 for(int j = 1;j <= 3;j ++) 86 { 87 temp[count] = r.map[i][j]; 88 count ++; 89 } 90 for(int i = 0;i < 9;i ++) 91 for(int j = i + 1;j < 9;j ++) 92 if(temp[j] < temp[i] && temp[j] && temp[i]) 93 sum ++; 94 return !(sum & 1); 95 } 96 97 bool check(const int x,const int y) 98 { 99 if(x >= 1 && x <= 3 && y >= 1 && y <= 3)100 return true;101 return false;102 }103 104 void cal_hash(Node & r)105 {106 int sum = 0,count = 0,box;107 int temp[10];108 109 for(int i = 1;i <= 3;i ++)110 for(int j = 1;j <= 3;j ++)111 {112 temp[count] = r.map[i][j];113 count ++;114 }115 for(int i = 0;i < 9;i ++)116 {117 box = 0;118 for(int j = i + 1;j < 9;j ++)119 if(temp[j] < temp[i])120 box ++;121 sum += (box * HASH[i]);122 }123 r.hash = sum;124 }125 126 void search(Node const & r)127 {128 Node cur,next;129 130 priority_queue
que;131 que.push(r);132 while(!que.empty())133 {134 cur = que.top();135 que.pop();136 for(int i = 0;i < 4;i ++)137 {138 next = cur;139 next.x = cur.x + UP_DATE[i][0];140 next.y = cur.y + UP_DATE[i][1];141 if(!check(next.x,next.y))142 continue;143 swap(next.map[cur.x][cur.y],next.map[next.x][next.y]);144 cal_hash(next);145 146 if(PATH[next.hash] == -1)147 {148 PATH[next.hash] = i;149 PRE[next.hash] = cur.hash;150 next.g ++;151 cal_h(next);152 que.push(next);153 }154 if(next.hash == GOAL)155 {156 show();157 return ;158 }159 }160 }161 162 }163 164 void cal_h(Node & r)165 {166 int ans = 0;167 for(int i = 1;i <= 3;i ++)168 for(int j = 1;j <= 3;j ++)169 if(r.map[i][j])170 ans += abs(i - ((r.map[i][j] - 1) / 3 + 1)) + abs(j - ((r.map[i][j] - 1) % 3 + 1));171 r.h = ans;172 }173 174 void show(void)175 {176 string ans;177 int hash = GOAL;178 179 ans.clear();180 while(PRE[hash] != -1)181 {182 switch(PATH[hash])183 {184 case 0:ans += 'l';break;185 case 1:ans += 'r';break;186 case 2:ans += 'u';break;187 case 3:ans += 'd';break;188 }189 hash = PRE[hash];190 }191 for(int i = ans.size() - 1;i >= 0;i --)192 printf("%c",ans[i]);193 cout << endl;194 }

 

转载于:https://www.cnblogs.com/xz816111/p/4366110.html

你可能感兴趣的文章
有利于seo优化的网站地图不能取巧
查看>>
快照产品体验优化
查看>>
ASCII
查看>>
ibatis SqlMap not found
查看>>
Android SD卡创建文件和文件夹失败
查看>>
Ubuntu 14.04 vsftp refusing to run with writable root inside chroot问题解决方法
查看>>
Intellij IDEA远程调试tomcat
查看>>
hadoop的学习论坛
查看>>
替代Windows Cmd的利器PowerCmd
查看>>
Struts2 学习小结
查看>>
Linux IPMI 安装配置实用
查看>>
烂泥:wordpress迁移到docker
查看>>
.扒渣机的性能及优势 
查看>>
Linux下磁盘保留空间的调整,解决df看到的空间和实际磁盘大小不一致的问题
查看>>
RSA 生成公钥、私钥对
查看>>
C# ASP.NET 权限设计 完全支持多数据库多语言包的通用权限管理系统组件源码
查看>>
测试工具综合
查看>>
asp.net中调用COM组件发布IIS时常见错误 80070005解决方案
查看>>
分享一段ios数据库代码,包括对表的创建、升级、增删查改
查看>>
如何书写高质量的jQuery代码
查看>>