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


推荐阅读
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • Highcharts翻译系列之二十:曲线图例子(二)
    Highcharts翻译系列之二十:曲线图例子(二)代码 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了指针的概念以及在函数调用时使用指针作为参数的情况。指针存放的是变量的地址,通过指针可以修改指针所指的变量的值。然而,如果想要修改指针的指向,就需要使用指针的引用。文章还通过一个简单的示例代码解释了指针的引用的使用方法,并思考了在修改指针的指向后,取指针的输出结果。 ... [详细]
  • 在project.properties添加#Projecttarget.targetandroid-19android.library.reference.1..Sliding ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • express工程中的json调用方法
    本文介绍了在express工程中如何调用json数据,包括建立app.js文件、创建数据接口以及获取全部数据和typeid为1的数据的方法。 ... [详细]
  • node.jsrequire和ES6导入导出的区别原 ... [详细]
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社区 版权所有