1604 - Cubic Eight-Puzzle
来源:互联网 发布:苹果手机安装不了淘宝 编辑:程序博客网 时间:2024/04/30 12:25
我有话说:
这道题叫做立体八数码问题。但绝对比八数码问题要难得多。一个是状态数量增加,另外一个是状态的难以表示。这道题的基本思路是双向广搜+深搜;并且对广搜的步数有一个上限,正向21,反向9,是试验过最快的一种。
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <map>#include <queue>#include <vector>using namespace std;struct Node{ int t,n,s; Node(int t,int n,int s):t(t),n(n),s(s){} bool operator < (const Node& a) const{ return t>a.t; }};map<char,int>mp;int ss[8]={1,6,36,216,1296,7776,46656,279936};//一个小方块状态有6种,一共有八个小方块,所以我们用八位六进制数来描述状态。int goal[9],path[9],vis[9][1679616],dist[9][1679616];int d[4][2]={{1,0},{-1,0},{0,-1},{0,1}};//上下左右int p[6][4]={ {2,2,5,5}, {4,4,3,3}, {0,0,4,4}, {5,5,1,1}, {1,1,2,2}, {3,3,0,0},};//移动后移动的方块朝上的面,因为我们定义(0,1),(2,3),(4,5)为三个对面分别为白,红,蓝三种颜色。并且x,y方向上颜色是固定的,因为我们没有旋转这个操作,请自行画图验证。所以比如2,3表示颜色相同那么统一定义为2好了。反正我们在下面最终状态的dfs生成中枚举了所有的状态priority_queue<Node>q[2];void dfs(int u,int gp){ if(u==9){ int sta=0,cnt=0; for(int i=0;i<9;i++){ if(path[i]!=-1){ sta+=ss[7-cnt]*path[i];//编码 cnt++; } } dist[gp][sta]=0; vis[gp][sta]=1; q[1].push(Node(0,gp,sta)); return; } if(goal[u]==1){ path[u]=0; dfs(u+1,gp); path[u]=1; dfs(u+1,gp); }else if(goal[u]==2){ path[u]=2; dfs(u+1,gp); path[u]=3; dfs(u+1,gp); }else if(goal[u]==3){ path[u]=4; dfs(u+1,gp); path[u]=5; dfs(u+1,gp); }else{ path[u]=-1; dfs(u+1,gp); }}void init(int x,int y){ while(!q[0].empty())q[0].pop(); while(!q[1].empty())q[1].pop(); memset(dist,-1,sizeof(dist)); memset(vis,-1,sizeof(vis)); dist[x*3+y][0]=0; vis[x*3+y][0]=0; q[0].push(Node(0,x*3+y,0)); for(int i=0;i<9;i++){ if(goal[i]==0){ dfs(0,i); break; } }}int getv(int p,int s){ for(int i=1;i<=8-p;i++) s/=6; return s%6;}int bfs(int id,int step){ while(!q[id].empty()){ Node u=q[id].top(); if(u.t>step)return -1; q[id].pop(); if(vis[u.n][u.s]==!id)return u.t; int gg[9]; int x=u.n/3,y=u.n%3; for(int i=0;i<4;i++){ int nx=x+d[i][0],ny=y+d[i][1]; if(nx<0||nx>2||ny<0||ny>2)continue; int s=u.s; for(int j=8;j>=0;j--){ if(j==u.n){ gg[j]=-1; }else{ gg[j]=s%6; s/=6; } } gg[u.n]=p[gg[nx*3+ny]][i]; gg[nx*3+ny]=-1; int sta=0,cnt=0; for(int j=0;j<9;j++){ if(gg[j]!=-1){ sta+=ss[7-cnt]*gg[j]; cnt++; } } if(vis[nx*3+ny][sta]!=id){ if(vis[nx*3+ny][sta]==-1){ vis[nx*3+ny][sta]=id; dist[nx*3+ny][sta]=u.t+1; q[id].push(Node(u.t+1,nx*3+ny,sta)); } else return u.t+1+dist[nx*3+ny][sta]; } } } return -1;}int solve(){ int step=0; while(!q[0].empty()||!q[1].empty()){ if(step>30)return -1; if(!q[0].empty()&&step<=21){ int k=bfs(0,step); if(k>30)return -1; if(k!=-1)return k; } if(!q[1].empty()&&step<=9){ int k=bfs(1,step); if(k>30)return -1; if(k!=-1)return k; } step++; } return -1;}int main(){ mp['E']=0,mp['W']=1,mp['R']=2,mp['B']=3; int x,y,gx,gy; char s[2]; while(scanf("%d%d",&y,&x)&&(x+y)){ --x;--y; for(int i=0;i<9;i++){ scanf("%s",s); goal[i]=mp[s[0]]; } init(x,y); printf("%d\n",solve()); } return 0;}
0 0
- 1604 - Cubic Eight-Puzzle
- Cubic Eight-Puzzle UVA
- LA 3618 Cubic Eight-Puzzle
- 搜索 POJ 3131 Cubic Eight-Puzzle
- POJ 3131 Cubic Eight-Puzzle 笔记
- POJ 3131 Cubic Eight-Puzzle 双向BFS + HASH
- POJ-3131-Cubic Eight-Puzzle(双向BFS+哈希)
- poj 3131 Cubic Eight-Puzzle (双向bfs+深度控制 立体八数码)
- poj 3131 Cubic Eight-Puzzle 双向广搜 Hash判重
- Eight Queens Puzzle
- hdu2514 Another Eight Puzzle
- Uestc-1490-Eight Puzzle
- Another Eight Puzzle
- Another Eight Puzzle
- HDU2514 Another Eight Puzzle
- 1023 Another Eight Puzzle
- Another Eight Puzzle
- UESTC1490 Eight Puzzle 双向BFS
- 益智游戏
- c#调用cmd(可输入指令)
- Repeater 分页 删除
- This Is How I Work
- (78)最长公共前缀
- 1604 - Cubic Eight-Puzzle
- 五、线程通信
- 第六周项目二 建立链栈算法库
- Java 299之输出二维数组中的最大值
- Intent scheme URL attack
- LayoutInflater的获取与使用
- 虚拟内存遍历 VMView
- 排序(2015-10-20)
- java 修饰符全解