码迷,mamicode.com
首页 > 其他好文 > 详细

UVA_Cubic Eight-Puzzle UVA 1604

时间:2015-05-04 13:45:42      阅读:376      评论:0      收藏:0      [点我收藏+]

标签:

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 <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <ctime>
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.step + b.h)
  return false;
 if (a.step + a.h == b.step + b.h && a.step < b.step)
  return false;
 return true;    
}

};

priority_queue<status> 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 << pos * 3 + j);
        else
         ns.g &= ~(1 << pos * 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 << bfs() << endl;     
  }
  cout << "Time use " << clock() - kk << endl;
 return 0;    
}

 

 

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

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

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

 

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <cstdio>
  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 < rear && front2 < 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 << pos * 3 + j);
151         else
152          ns.g &= ~(1 << pos * 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 << pos * 3 + j);
193         else
194          ns.g &= ~(1 << pos * 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 << bfs() << endl;     
288   }
289  return 0;    
290 }

 

UVA_Cubic Eight-Puzzle UVA 1604

标签:

原文地址:http://www.cnblogs.com/Xiper/p/4475845.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!