热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

UVA_CubicEightPuzzleUVA1604

立体八数码,双向BFS+二进制状态压缩

Let‘s play a puzzle using eight cubes placed on a 3 x 3 board leaving one empty square.
Faces of cubes are painted with three colors. As a puzzle step, you can roll one of the cubes to the adjacent
empty square. Your goal is to make the specified color pattern visible from above by a number of such steps.
The rules of this puzzle are as follows.
Coloring of Cubes: All the cubes are colored in the same way as shown in Figure 3. The opposite
faces have the same color.
Figure 3: Coloring of a cube

技术分享
1.Initial Board State: Eight cubes are placed on the 3 x 3 board leaving one empty square. All the
cubes have the same orientation as shown in Figure 4. As shown in the figure, squares on the board
are given x and y coordinates, (1, 1), (1, 2), ..., and (3, 3). The position of the initially empty square
may vary.
技术分享
Figure 4: Initial board state
2.Rolling Cubes: At each step, we can choose one of the cubes adjacent to the empty square and roll it
into the empty square, leaving the original position empty. Figure 5 shows an example.
Figure 5: Rolling a cube

技术分享

3.Goal: The goal of this puzzle is to arrange the cubes so that their top faces form the specified color
pattern by a number of cube rolling steps described above.
4.Your task is to write a program that finds the minimum number of steps required to make the specified color
pattern from the given initial state.
Input
The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated
by a space. The number of datasets is less than 16. Each dataset is formatted as follows.
x y
F
11 F21 F31
F
12 F22 F32
F
13 F23 F33
The first line contains two integers x and y separated by a space, indicating the position (x, y) of the initially
empty square. The values of x and y are 1, 2, or 3.
The following three lines specify the color pattern to make. Each line contains three characters F1j, F2j, and
F
3j, separated by a space. Character Fij indicates the top color of the cube, if any, at position (i, j) as follows:
B:
Blue,
W:
White,
R:
Red,
E:
the square is Empty.
There is exactly one `E‘ character in each dataset.
Output
For each dataset, output the minimum number of steps to achieve the goal, when the goal can be reached
within 30 steps. Otherwise, output ``-1‘‘ for the dataset.
3618 - Cubic Eight-Puzzle 2/3
Sample Input
1 2
W W W
E W W
W W W
2 1
R B W
R W W
E W W
3 3
W B W
B R E
R B R
3 3
B W R
B W R
B E R
2 1
B B B
B R B
B R E
1 1
R R R
W W W
R R E
2 1
R R R
B W B
R R E
3 2
R R R
W E W
R R R
0 0
Sample Output
0
3
13
23
29
30
-1
-1

解题报告

难度。。很大,BFS这个没有疑问,那么究竟是A*还是双广呢,由于本题的状态数很多,且转移方程很麻烦,所以首先考虑A*.

估价函数这里不在多说(其实是我忘了),但提交后TLE...,CODE如下

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int MaxHashSize = 1526597;
const int MaxState = 2500000;
int tot,target[256];
char g[9];
int dir[4][2] = {0,1,0,-1,-1,0,1,0};
int getdia[6][4] = {5,5,2,2,3,3,4,4,4,4,0,0,1,1,5,5,2,2,1,1,0,0,3,3};


typedef struct status
{
char  pos;
char  step;
int   g;    
char  h;
friend bool operator <(const status& a ,const status& b)
{
 if (a.step + a.h  b.h)
  return false;
 if (a.step + a.h == b.step + b.h && a.step < b.step)
  return false;
 return true;    
}

};

priority_queue q;

status start;
int Head[MaxHashSize],Next[MaxState];
status st[MaxState];
void init_Hash()
{
 memset(Head,-1,sizeof(Head));    
}

int GetHashValue(status &x)
{
 return x.g % MaxHashSize;
}

bool insert_Hash(int id)
{
 int h = GetHashValue(st[id]);
 int u = Head[h];
 while(u != -1)
 {
     if (st[u].g == st[id].g)
      return false;
    u = Next[u];
 }
 Next[id] = Head[h];
 Head[h] = id;
 return true;
}

int caculateh(status &x)
{
 int res = 0;
 int ok = 1;
 for(int i = 0 ; i <9 ; ++ i)
  {
      int temp = 0;
      for(int j = 0 ; j <3 ; ++ j)
       {
        int s = (x.g >> (3*i + j)) & 1;
       temp |= (s << j);    
     }
    if ( (temp == 0 || temp == 1) && g[i] != W)
     res ++ ;
    else if ( (temp == 2 || temp == 3) && g[i] !=R)
     res ++;
    else if ( (temp == 4 || temp == 5) && g[i] != B)
     res ++;
    else if (temp == 7 && g[i] != E )
     {
      res ++;    
      ok = 0;
     }
     
  }
if (ok)
 return res;
else
 return res - 1;
 
}


int bfs()
{
 int frOnt= 0 ,rear = 1;
 q.push(start);
 while(!q.empty())
  {
    status ss = q.top();q.pop();
    st[front++] = ss;
    if (ss.h == 0)
     return ss.step;
    if (ss.h + ss.step > 30)
     return -1;
    int pos = ss.pos;
    int x = pos / 3;
    int y = pos % 3;
    int step = ss.step;
    int g = ss.g;
    for(int i = 0 ; i <4 ; ++ i)
     {
       int newx = x + dir[i][0];
       int newy = y + dir[i][1];
       if (newx >= 3 || newx <0 || newy >= 3 || newy <0)
        continue;
       int newpos = newx * 3 + newy;
       status ns = ss;
       int temp = 0;
       for(int j = 0 ; j <3 ; ++ j)
        {
            int s = (g >> (newpos * 3 + j) )  & 1;
            temp |= (s << j);
        }
       int sis = getdia[temp][i];
       for(int j = 0 ; j <3 ;++ j)
        ns.g |= (1 <<(newpos*3 + j));
       for(int j = 0 ; j <3 ; ++ j)
        if (sis >> j & 1)
         ns.g |= (1 <3 + j);
        else
         ns.g &= ~(1 <3 + j);
       ns.step = step + 1;
       ns.pos = newpos;
       ns.h = caculateh(ns);
       st[rear] = ns;
       if (insert_Hash(rear))
        {
             q.push(ns);
             rear++;
        }
      }    
  }
 return -1;
}


int main(int argc, char * argv[])
{
 int kk = clock();
 int s1,s2;
 while(scanf("%d%d%*c",&s1,&s2) && s1)
  { 
    tot = 0;
      for(int i = 0 ; i <9 ; ++ i)
       scanf("%c%*c",&g[i]);
    int fp = (s2-1) * 3 + s1 - 1;
    start.pos = fp;
    start.g = 0;
    init_Hash();
    for(int i = 0 ; i <3 ; ++ i)
     start.g |= (1 <<(3*fp+i));
    st[0] = start;
    insert_Hash(0);
    start.h = caculateh(start);
    start.step = 0;
    while(!q.empty())
     q.pop();
    cout < endl;     
  }
  cout <<"Time use " < endl;
 return 0;    
}

这里的代码中有Clock(),大家可以试试几组数据,30步的极限或者-1,速度非常慢。。(无法忍受)

那么,我们只能改用双广了,因为末状态有256种,所以我们用一个dfs把末状态压进去,提交后AC~

顺便多题一句双广复杂度是 2*n^(a/2) ,而单向的是n^a,code 如下

  1 #include 
  2 #include 
  3 #include 
  4 #include 
  5 using namespace std;
  6 const int MaxHashSize = 1526597;
  7 const int MaxState = 2500000;
  8 int tot,target[256],ssl;
  9 char g[9];
 10 int dir[4][2] = {0,1,0,-1,-1,0,1,0};
 11 int getdia[6][4] = {5,5,2,2,3,3,4,4,4,4,0,0,1,1,5,5,2,2,1,1,0,0,3,3};
 12 
 13 
 14 typedef struct status
 15 {
 16 char  pos;
 17 char  step;
 18 int   g;    
 19 };
 20 
 21 status start;
 22 int Head[MaxHashSize],Next[MaxState];
 23 int Head2[MaxHashSize],Next2[MaxState];
 24 status st[MaxState];
 25 status st2[MaxState];
 26 
 27 void init_Hash()
 28 {
 29  memset(Head,-1,sizeof(Head));    
 30  memset(Head2,-1,sizeof(Head));    
 31 }
 32 
 33 int GetHashValue(status &x)
 34 {
 35  return x.g % MaxHashSize;
 36 }
 37 
 38 bool insert_Hash(int id ,int l)
 39 {
 40  int h;
 41  if (l == 0)
 42   h = GetHashValue(st[id]);
 43  else
 44   h = GetHashValue(st2[id]);
 45  int u;
 46  if (l == 0)
 47   u = Head[h];
 48  else
 49   u = Head2[h];
 50  
 51  while(u != -1)
 52  {
 53      if (l == 0)
 54       {
 55      if (st[u].g == st[id].g)
 56       return false;
 57     u = Next[u];
 58      }
 59     else
 60      {
 61     if (st2[u].g == st2[id].g)
 62       return false;
 63     u = Next2[u];    
 64      }
 65  }
 66  if (l == 0)
 67   {
 68     Next[id] = Head[h];
 69     Head[h] = id;    
 70   }
 71  else
 72   {
 73       Next2[id] = Head2[h];
 74     Head2[h] = id;
 75   }
 76  return true;
 77 }
 78 
 79 
 80 int meet(int id,int l)
 81 {
 82  int u,h;
 83  if (l == 0)
 84   {
 85     h = GetHashValue(st[id]);
 86     int u = Head2[h];
 87     while(u != -1)
 88      {
 89          if (st2[u].g == st[id].g)
 90           return st[id].step + st2[u].step;
 91            u = Next2[u];
 92      }
 93      
 94     return -1;
 95   }
 96  else
 97   {
 98     h = GetHashValue(st2[id]);
 99     int u = Head[h];
100     while(u != -1)
101      {
102          if (st[u].g == st2[id].g)
103           return st[u].step + st2[id].step;
104            u = Next[u];
105      }
106      
107     return -1;
108   }
109 }
110 
111 
112 int bfs()
113 {
114  int frOnt= 0 ,rear = 1;
115  int front2 = 0 , rear2 = 256;
116  while(front  rear2)
117   {
118       if (1)
119       {
120     status ss = st[front++] ;
121     int ans = meet(front-1,0);
122     if (ans != -1)
123      return ans > 30 ? -1 : ans;
124     if (ss.step >= 30)
125      return -1;
126     int pos = ss.pos;
127     int x = pos / 3;
128     int y = pos % 3;
129     int step = ss.step;
130     int g = ss.g;
131     for(int i = 0 ; i <4 ; ++ i)
132      {
133        int newx = x + dir[i][0];
134        int newy = y + dir[i][1];
135        if (newx >= 3 || newx <0 || newy >= 3 || newy <0)
136         continue;
137        int newpos = newx * 3 + newy;
138        status ns = ss;
139        int temp = 0;
140        for(int j = 0 ; j <3 ; ++ j)
141         {
142             int s = (g >> (newpos * 3 + j) )  & 1;
143             temp |= (s << j);
144         }
145        int sis = getdia[temp][i];
146        for(int j = 0 ; j <3 ;++ j)
147         ns.g |= (1 <<(newpos*3 + j));
148        for(int j = 0 ; j <3 ; ++ j)
149         if (sis >> j & 1)
150          ns.g |= (1 <3 + j);
151         else
152          ns.g &= ~(1 <3 + j);
153        ns.step = step + 1;
154        ns.pos = newpos;
155        st[rear] = ns;
156        if (insert_Hash(rear,0))
157         {
158              rear++;
159         }
160       }    
161     }
162       status ss = st2[front2++] ;
163     int ans = meet(front2-1,1);
164     if (ans != -1)
165      return ans > 30 ? -1 : ans;
166     if (ss.step >= 30)
167      return -1;
168     int pos = ss.pos;
169     int x = pos / 3;
170     int y = pos % 3;
171     int step = ss.step;
172     int g = ss.g;
173     for(int i = 0 ; i <4 ; ++ i)
174      {
175        int newx = x + dir[i][0];
176        int newy = y + dir[i][1];
177        if (newx >= 3 || newx <0 || newy >= 3 || newy <0)
178         continue;
179        int newpos = newx * 3 + newy;
180        status ns = ss;
181        int temp = 0;
182        for(int j = 0 ; j <3 ; ++ j)
183         {
184             int s = (g >> (newpos * 3 + j) )  & 1;
185             temp |= (s << j);
186         }
187        int sis = getdia[temp][i];
188        for(int j = 0 ; j <3 ;++ j)
189         ns.g |= (1 <<(newpos*3 + j));
190        for(int j = 0 ; j <3 ; ++ j)
191         if (sis >> j & 1)
192          ns.g |= (1 <3 + j);
193         else
194          ns.g &= ~(1 <3 + j);
195        ns.step = step + 1;
196        ns.pos = newpos;
197        st2[rear2] = ns;
198        if (insert_Hash(rear2,1))
199         {
200              rear2++;
201         }
202       }    
203   }
204  return -1;
205 }
206 
207 
208 
209 void dfs(int n,int temp)
210 {
211  if (n == 9)
212   {
213       st2[tot].g = temp;
214       st2[tot].step = 0;
215       insert_Hash(tot,1);
216       st2[tot++].pos = ssl;
217   }
218  else
219   {
220       int f;
221       if (g[n] == W)
222        {
223         f = temp;
224        dfs(n+1,f);
225           f |= (1 <<(3*n));
226        dfs(n+1,f);
227      }
228     else if(g[n] == R)
229      {
230          f = temp;
231          f |= (1 <<(3*n+1));
232          dfs(n+1,f);
233          f |= (1 <<3*n);
234          dfs(n+1,f);
235      }
236     else if(g[n] == B)
237      {
238          f = temp;
239          f |= (1 <<3*n+2);
240          dfs(n+1,f);
241          f |= (1 <<3*n);
242          dfs(n+1,f);
243      }
244     else if(g[n] == E)
245      {
246          f = temp;
247          for(int j = 0 ; j <3 ; ++ j)
248           f |= (1 <<3*n + j);
249            dfs(n+1,f);
250      }
251   }
252 }
253 
254 
255 
256 
257 
258 
259 
260 
261 
262 
263 
264 
265 int main(int argc, char * argv[])
266 {
267  int s1,s2;
268  while(scanf("%d%d%*c",&s1,&s2) && s1)
269   { 
270     tot = 0;
271       for(int i = 0 ; i <9 ; ++ i)
272         {
273            scanf("%c%*c",&g[i]);
274            if (g[i] == E)
275             ssl = i;
276        }
277     int fp = (s2-1) * 3 + s1 - 1;
278     start.pos = fp;
279     start.g = 0;
280     init_Hash();
281     dfs(0,0);
282     for(int i = 0 ; i <3 ; ++ i)
283      start.g |= (1 <<(3*fp+i));
284     st[0] = start;
285     insert_Hash(0,0);
286     start.step = 0;
287     cout < endl;     
288   }
289  return 0;    
290 }

UVA_Cubic Eight-Puzzle UVA 1604


推荐阅读
  • Android日历提醒软件开源项目分享及使用教程
    本文介绍了一款名为Android日历提醒软件的开源项目,作者分享了该项目的代码和使用教程,并提供了GitHub项目地址。文章详细介绍了该软件的主界面风格、日程信息的分类查看功能,以及添加日程提醒和查看详情的界面。同时,作者还提醒了读者在使用过程中可能遇到的Android6.0权限问题,并提供了解决方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 在project.properties添加#Projecttarget.targetandroid-19android.library.reference.1..Sliding ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • EPPlus绘制刻度线的方法及示例代码
    本文介绍了使用EPPlus绘制刻度线的方法,并提供了示例代码。通过ExcelPackage类和List对象,可以实现在Excel中绘制刻度线的功能。具体的方法和示例代码在文章中进行了详细的介绍和演示。 ... [详细]
author-avatar
冰雪聪明
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有