热门标签 | 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


推荐阅读
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • Docker的安全基准
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • QUIC协议:快速UDP互联网连接
    QUIC(Quick UDP Internet Connections)是谷歌开发的一种旨在提高网络性能和安全性的传输层协议。它基于UDP,并结合了TLS级别的安全性,提供了更高效、更可靠的互联网通信方式。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 使用Numpy实现无外部库依赖的双线性插值图像缩放
    本文介绍如何仅使用Numpy库,通过双线性插值方法实现图像的高效缩放,避免了对OpenCV等图像处理库的依赖。文中详细解释了算法原理,并提供了完整的代码示例。 ... [详细]
  • 程序员妻子吐槽:丈夫北漂8年终薪3万,存款情况令人意外
    一位程序员的妻子在网上分享了她丈夫在北京工作八年的经历,月薪仅3万元,存款情况却出乎意料。本文探讨了高学历人才在大城市的职场现状及生活压力。 ... [详细]
  • CSS 布局:液态三栏混合宽度布局
    本文介绍了如何使用 CSS 实现液态的三栏布局,其中各栏具有不同的宽度设置。通过调整容器和内容区域的属性,可以实现灵活且响应式的网页设计。 ... [详细]
  • Linux 系统启动故障排除指南:MBR 和 GRUB 问题
    本文详细介绍了 Linux 系统启动过程中常见的 MBR 扇区和 GRUB 引导程序故障及其解决方案,涵盖从备份、模拟故障到恢复的具体步骤。 ... [详细]
  • 本文介绍了如何使用jQuery根据元素的类型(如复选框)和标签名(如段落)来获取DOM对象。这有助于更高效地操作网页中的特定元素。 ... [详细]
  • 深入理解Tornado模板系统
    本文详细介绍了Tornado框架中模板系统的使用方法。Tornado自带的轻量级、高效且灵活的模板语言位于tornado.template模块,支持嵌入Python代码片段,帮助开发者快速构建动态网页。 ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
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社区 版权所有