UVa 704 - Colour Hash, 双向bfs,很给力
来源:互联网 发布:关联矩阵邻接矩阵 编辑:程序博客网 时间:2024/05/16 10:09
链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=110&page=show_problem&problem=645
类型:隐式图搜索,双向bfs
原题:
This puzzle consists of two wheels. Both wheels can rotate both clock and counter-clockwise. They contain 21 coloured pieces, 10 of which are rounded triangles and 11 of which are separators. Figure 1 shows the final position of each one of the pieces. Note that to perform a one step rotation you must turn the wheel until you have advanced a triangle and a separator.
Figure 1. Final puzzle configuration
Your job is to write a program that reads the puzzle configuration and prints the minimum sequence of movements required to reach the final position. We will use the following integer values to encode each type of piece:
A puzzle configuration will be described using 24 integers, the first 12 to describe the left wheel configuration and the last 12 for the right wheel. The first integer represents the bottom right separator of the left wheel and the next eleven integers describe the left wheel clockwise. The thirteenth integer represents the bottom left separator of right wheel and the next eleven integers describe the right wheel counter-clockwise.
The final position is therefore encoded like:
If for instance we rotate the left wheel clockwise one position from the final configuration (as shown in Figure 2) the puzzle configuration would be encoded like:
Figure 2. The puzzle after rotating the left wheel on step clockwise from the final configuration.
题目大意:
有一种拼盘有两个轮子, 而这两个轮子都可以顺时针转和逆时针转. 拼盘有21 片, 10 片是有点圆的三角形, 而另外11 片则是骨头型. 图1 是所要拼成的目标. 记住一个"步骤"是你必须转动其中一个轮子往顺时针或逆时针的方向直到拼盘的每一片的边缘都能和他旁边的那几片的边缘重合在一起.
你的任务是写一个程式读入拼盘一开始的状态并且输出一个能够达成目标的最短转动序列,我们会用底下的数字来表示每一片:
0 灰色(骨头型)
1 黄色(三角形)
2 黄色(骨头型)
3 蓝色(三角形)
4 蓝色(骨头型)
5 紫色(三角形)
6 紫色(骨头型)
7 绿色(三角形)
8 绿色(骨头型)
9 红色(三角形)
10 红色(骨头型)
0 3 4 3 0 5 6 5 0 1 2 1 0 7 8 7 0 9 10 9 0 1 2 1
2 1 0 3 4 3 0 5 6 5 0 1 0 7 8 7 0 9 10 9 0 5 0 1
/* UVa 704 - Colour Hash * Time : 0.140s (UVA) * 双向搜索 + map判重 */#include<iostream>#include<cstring>#include<cstdio>#include<map>#include<string>#define MAXN 1000000using namespace std;map<string, int>vis;map<string, int>back_vis;typedef int State[24];State goal = {0, 3, 4, 3, 0, 5, 6, 5, 0, 1, 2, 1, 0, 7, 8, 7, 0 ,9, 10,9 ,0, 1, 2, 1}, start; State que[MAXN];int step[MAXN], father[MAXN], path[MAXN], ans;int back_father[MAXN], back_path[MAXN];// 旋转函数void rotate(int *next, int *origin, int dir){ if(dir==1){ // 左盘顺时针转 next[0] = origin[10], next[1] = origin[11]; memcpy(next+2, origin, sizeof(int)*10); // 大块的,连续数组元素的用memcpy节约时间 memcpy(next+12, origin+12, sizeof(int)*9); next[21]=origin[7], next[22] = origin[8], next[23] = origin[9]; } else if(dir==2){ // 右盘顺时针转 memcpy(next+12, origin+14, sizeof(int)*10); next[22] = origin[12], next[23] = origin[13]; memcpy(next, origin, sizeof(int)*9); next[9] = next[21], next[10] = next[22], next[11] = next[23]; } else if(dir==3){ // 左盘逆时针转 memcpy(next, origin+2, sizeof(int)*10); next[10] = origin[0], next[11] = origin[1]; memcpy(next+12, origin+12, sizeof(int)*9); next[21]=next[9], next[22]=next[10], next[23]=next[11]; } else if(dir==4){ // 右盘逆时针转 next[12] = origin[22], next[13] = origin[23]; memcpy(next+14, origin+12, sizeof(int)*10); memcpy(next, origin, sizeof(int)*9); next[9] = next[21], next[10] = next[22], next[11] = next[23]; }}// 把状态转换成字符串inline string change_state(State &s){ string str; for(int i=0; i<24; ++i) str += s[i]+'0'; return str;} inline int try_to_insert(int s){ string str = change_state(que[s]); if(!vis[str]){ vis[str]=1; return true; } return false;} inline int back_try_to_insert(int s){ string str = change_state(que[s]); if(!back_vis[str]){ back_vis[str]=s; //保存在队列在队列中的位置,而不是1或者true,方便后面输出路径 return true; } return false; }bool back_bfs(){ //逆向搜索 memset(back_father, 0, sizeof(back_father)); step[0] = step[1] = 0; back_vis.clear(); back_vis[change_state(goal)] = 1; int front=0, rear=1; memcpy(que[0], goal, sizeof(goal)); while(front < rear){ State &s = que[front]; if(step[front] > 8){ // 超过8步不再搜索 ++front; continue; } for(int i=1; i<=4; ++i){ State &next = que[rear]; rotate(next, s, i); step[rear] = step[front]+1; if(back_try_to_insert(rear)){ back_father[rear] = front; switch(i){ // 因为是逆向搜索,所以方向保存的也要是相反的 case 1:back_path[rear] = 3;break; case 2:back_path[rear] = 4;break; case 3:back_path[rear] = 1;break; case 4:back_path[rear] = 2;break; } rear++; } } ++front; } return false;}bool bfs(){ // 正向搜索 memset(father, 0, sizeof(father)); step[0] = 0; vis.clear(); vis[change_state(start)] = 1; int front=0, rear=1; memcpy(que[0], start, sizeof(start)); while(front < rear){ State &s = que[front]; if(step[front] > 8) {++front; continue;} if(memcmp(s, goal, sizeof(goal))==0){ ans = front; return false; } if(back_vis[change_state(s)]){ ans = front; return true; } for(int i=1; i<=4; ++i){ State &next = que[rear]; rotate(next, s, i); step[rear] = step[front]+1; if(try_to_insert(rear)){ father[rear]=front; path[rear]=i; rear++; } } ++front; } ans = -1;}void print_path(int cur){ // 打印出正向搜索部分 if(cur){ print_path(father[cur]); printf("%d",path[cur]); }}void print_back(){ // 打印出逆向搜索部分 string str = change_state(que[ans]); int cur = back_vis[str]; while(cur){ printf("%d", back_path[cur]); cur = back_father[cur]; }}int main(){ freopen("input.txt","r",stdin); int T; back_bfs(); // 逆向搜索只需要一次就够了 scanf("%d", &T); while(T--){ for(int i=0; i<24; ++i) scanf("%d", &start[i]); if(memcmp(start, goal, sizeof(goal))==0) printf("PUZZLE ALREADY SOLVED\n"); else{ bfs(); if(ans!=-1){ print_path(ans); print_back(); printf("\n"); } else printf("NO SOLUTION WAS FOUND IN 16 STEPS\n"); } } return 0;}
—— 生命的意义,在于赋予它意义。
原创 http://blog.csdn.net/shuangde800 , By D_Double (转载请标明)
- UVa 704 - Colour Hash, 双向bfs,很给力
- uva 704 - Colour Hash map+双向bfs
- Colour Hash (Uva 704 双向bfs)
- UVA - 704 Colour Hash(双向bfs+hash+线性表)
- 704 - Colour Hash(双向bfs)
- UVA 704 Colour Hash (双向bfs + 判重)
- uva 704 - Colour Hash
- uva:704 - Colour Hash
- uva 704 Colour Hash
- UVa 704 - Colour Hash
- [UVA] 704 Colour Hash
- 704 - Colour Hash
- 704 - Colour Hash
- 704 - Colour Hash
- 704 - Colour Hash
- UVa Problem 704 Colour Hash (色彩缤纷游戏)
- UVa Problem 704 Colour Hash (色彩缤纷游戏)
- uva 704 Colour Hash(隐式图搜索+ 模拟)
- 对以下的三个字符串,按字典顺序将他们排序
- 输入一个字符串,存储在字符数组里,用指针的方式逐一显示字符,并求其长度
- mongodb那些事--复制数据库和表
- Asp.net网站发布过程
- 大数阶乘
- UVa 704 - Colour Hash, 双向bfs,很给力
- mongodb命令
- C#递归遍历TreeView节点
- js鼠标事件
- Dell 台式机蓝屏--硬盘坏道的前兆
- Linux 系统内核空间与用户空间通信的实现与分析
- js正则判断电话/手机/邮箱/
- 旧日志
- JVM调优(四):垃圾回收面临的问题