银河

SKYIV STUDIO

  博客园 :: 首页 :: 博问 :: 闪存 :: :: :: 订阅 订阅 :: 管理 ::
Timus 1016. A Cube on the Walk 要求给出一个立方体在国际象棋棋盘上的最短路径。

1016. A Cube on the Walk

Time Limit: 2.0 second
Memory Limit: 16 MB
A cube placed on some square of a usual chessboard. A cube completely covers one square of the chessboard but not anything more, i.e. size of cube’s edge is equal to the size of square’s edge. The integer number N (0 ≤ N ≤ 1000) is written on the each side of the cube. However it does not imply that the same number is written on all sides. On the different sides there are might be different numbers. One can move a cube to the next square by rotating it around the common edge of the cube and the square. During this motion the sum of the numbers on the bottom of the cube is calculated (each number is added as much times as it appeared at the bottom of the cube). Your task is to find the route between two given squares with the minimal sum of numbers on the bottom side. The numbers on the bottom at the beginning and at the end of walk are also counted. The start and the end positions are different.

Input

The only line of the input contains the necessary data set (only spaces used as delimiters). First, the start position is given, and then the end position. Each position is composed from the character (from ‘a’ to ‘h’ inclusively, it defines the number of the column on the chessboard) and the digit (from ‘1’ to ‘8’ inclusively, it defines the number of the row). That positions are followed by 6 numbers which are currently written on the forward, backward, top, right, bottom and left sides of the cube correspondingly.

Output

The only line of the output must contain the minimal sum followed by the optimal route (one of possible routes with minimal sum). The route must be represented by the sequence of cube’s positions during the walk. It begins with the start square and ends with the finish square. All square positions on the chessboard should be given in the same format as in input. Use spaces as delimiters.

Sample

input output
e2 e3 0 8 1 2 1 1
5 e2 d2 d1 e1 e2 e3
Problem Source: Ural State University Internal Contest '99 #2

这道题目是说,一个立方体放在国际象棋棋盘的一个格子上,该立方体每一面都和棋盘的格子一样大。该立方体每一面都标有一个非负整数。你可以在棋盘上滚动该立方体,在这期间计算立方体底面数字的和。你的任务是找出一条从给定的起点到终点的路径,使得前面所说的和最小。

输入只有一行,使用空格作为分隔符。首先是棋盘上的起点和终点的坐标,然后是立方体上的六个整数,按顺序为:前、后、顶、右、底、左面。举例如下: e2 e3 0 8 1 2 1 1

输出也只有一行,使用空格作为分隔符。首先是所求的最小的和。然后依次给出所求的路径的坐标。举例如下:5 e2 d2 d1 e1 e2 e3 。这个路径共六步,其长度为:1 + 1 + 0 + 1 + 1 + 1 = 5

上面的输入和输出的例子是题目中给出的。其实同一个输入可能不止一条最短路径。例如使用我的程序得到的输出如下:5 e2 e1 f1 f2 e2 e3 。这个路径也是六步,其长度为: 1 + 0 + 2 + 1 + 0 + 1 = 5



好了,我们还是来看程序吧。

第 43 到 116 行的 Cube 类代表立方体。

第 45 到 47 行的 X、Y、Z 表示立方体绕三个坐标轴旋转,如图所示。

第 48 行的 DCube 数组的四个元素表示立方体在棋盘上向“左、上、右、下”滚动。与此相对应的第 53 行的 DSize 数组的四个元素表示与棋盘当前格子相邻的“左、上、右、下”格子。

第 49 行的 Levels 数组共有 24 个元素,表示同一立方体的 24 种不同的状态,是通过调用第 106 到 115 行的 GetLevels 方法得到的。类似地,“Timus 1015. Test the Difference! 要求将赌场中的骰子分类” 中每种骰子也对应 24 种不同的状态。

程序的主体是第 123 到 130 行的 Run 方法。该方法的第 126 行调用 Read 方法获取输入。然后在第 127 行调用 Dijkstra 方法寻找最短路径。最后在第 128 到 129 行输出结果。

第 142 到 164 行的 Dijkstra 方法是程序的关键部分。第 144 行的三维数组 prev 用来记录立方体的路径,由 24 层的 8x8 棋盘构成。第 145 行的优先队列 q 的元素类型是 Rectangle,其构造函数的参数是 new Comparer() 。Comparer 类在第 11 到 17 行定义,用于逆序比较 Rectangle 的 Width 属性,该 Width 属性表示所求的最小的和。第 146 行将立方体的初始位置压入优先队列。第 147 行的三维数组 dist 大小是 8x8x24,用来记录路径长度,其元素被初始化为无穷大。第 150 到 162 行的循环使用 Dijkstra 算法寻找最短路径。最后在第 163 行调用 GetPath 方法返回找到的最短路径。

  1 using System;
  2 using System.IO;
  3 using System.Drawing;
  4 using System.Collections.Generic;
  5 
  6 namespace Skyiv.Ben.Timus
  7 {
  8   // http://acm.timus.ru/problem.aspx?space=1&num=1016
  9   sealed class T1016
 10   {
 11     sealed class Comparer : IComparer<Rectangle>
 12     {
 13       public int Compare(Rectangle x, Rectangle y)
 14       {
 15         return (x.Width == y.Width) ? 0 : ((x.Width < y.Width) ? 1 : -1);
 16       }
 17     }
 18   
 19     sealed class PriorityQueue<T>
 20     {
 21       List<T> queue = new List<T>();
 22       IComparer<T> comparer;
 23       
 24       public PriorityQueue(IComparer<T> comparer)
 25       {
 26         this.comparer = comparer;
 27       }
 28       
 29       public void Push(T v)
 30       {
 31         int i = queue.BinarySearch(v, comparer);
 32         queue.Insert((i < 0? ~i : i, v);
 33       }
 34       
 35       public T Pop()
 36       {
 37         T v = queue[queue.Count - 1];
 38         queue.RemoveAt(queue.Count - 1);
 39         return v;
 40       }
 41     }
 42     
 43     sealed class Cube : IEquatable<Cube>, IComparable<Cube>
 44     {
 45       static readonly Cube X = new Cube(015234);
 46       static readonly Cube Y = new Cube(241305);
 47       static readonly Cube Z = new Cube(352140);
 48       static readonly Cube[] DCube = { X, Y, X * X * X, Y * Y * Y };
 49       static readonly Cube[] Levels = GetLevels();
 50       static readonly int idxBottom = 4;
 51       public static readonly int Size = 8// for chessboard: 8x8
 52       public static readonly int Level = Levels.Length; // 24
 53       public static readonly Size[] DSize = { new Size(-1,0), new Size(0,1), new Size(1,0), new Size(0,-1) };
 54       
 55       int[] v = new int[6]; // Forward, Backward, Top, Right, Bottom, Left
 56       public int Bottom { get { return v[idxBottom]; } }
 57       
 58       Cube()
 59       {
 60         for (int i = 0; i < v.Length; i++) v[i] = i;
 61       }
 62       
 63       public Cube(params int[] v)
 64       {
 65         for (int i = 0; i < v.Length; i++this.v[i] = v[i];
 66       }
 67       
 68       public bool Equals(Cube other)
 69       {
 70         return CompareTo(other) == 0;
 71       }
 72       
 73       public int CompareTo(Cube other)
 74       {
 75         int i = 0;
 76         while (i < v.Length && v[i] == other.v[i]) i++;
 77         return (i == v.Length) ? 0 : ((v[i] < other.v[i]) ? -1 : 1);
 78       }
 79       
 80       public static Cube operator*(Cube x, Cube y)
 81       {
 82         Cube z = new Cube();
 83         for (int i = 0; i < z.v.Length; i++) z.v[y.v[i]] = x.v[i];
 84         return z;
 85       }
 86       
 87       public static Cube operator/(Cube x, Cube y)
 88       {
 89         Cube z = new Cube();
 90         for (int i = 0; i < z.v.Length; i++) z.v[i] = y.v[x.v[i]];
 91         return z;
 92       }
 93 
 94       public static int GetLevel(int level, int n)
 95       {
 96         return Array.BinarySearch(Levels, Levels[level] / DCube[n]);
 97       }
 98       
 99       public int GetBottom(int level)
100       {
101         int i = 0;
102         while (Levels[level].v[i] != idxBottom) i++;
103         return v[i];
104       }
105       
106       static Cube[] GetLevels()
107       {
108         List<Cube> list = new List<Cube>();
109         Cube v, x = new Cube(), y = new Cube(), z = new Cube();
110         for (int i = 0; i < 4; i++, x *= X)
111           for (int j = 0; j < 4; j++, y *= Y)
112             for (int n, k = 0; k < 4; k++, z *= Z)
113               if ((n = list.BinarySearch(v = x * y * z)) < 0) list.Insert(~n, v);
114         return list.ToArray();
115       }
116     }
117     
118     static void Main()
119     {
120       new T1016().Run(Console.In, Console.Out);
121     }
122     
123     void Run(TextReader reader, TextWriter writer)
124     {
125       Point start, end;
126       Cube cube = Read(reader, out start, out end);
127       Point[] path = Dijkstra(cube, start, end);
128       writer.Write(path[0].X);
129       for (int i = 1; i < path.Length; i++) writer.Write(PutPosition(path[i]));
130     }
131     
132     Cube Read(TextReader reader, out Point start, out Point end)
133     {
134       string[] ss = reader.ReadLine().Split();
135       start = GetPosition(ss[0]);
136       end = GetPosition(ss[1]);
137       int[] v = new int[ss.Length - 2];
138       for (int i = 0; i < v.Length; i++) v[i] = int.Parse(ss[i + 2]);
139       return new Cube(v);
140     }
141     
142     Point[] Dijkstra(Cube cube, Point start, Point end)
143     {
144       Rectangle[,,] prev = new Rectangle[Cube.Size, Cube.Size, Cube.Level];
145       PriorityQueue<Rectangle> q = new PriorityQueue<Rectangle>(new Comparer());
146       q.Push(new Rectangle(start.X, start.Y, cube.Bottom, 0));
147       int[,,] dist = GetDistance();
148       dist[start.X, start.Y, 0= cube.Bottom;
149       Rectangle v;
150       while ((v = q.Pop()).Location != end)
151         if (v.Width <= dist[v.X, v.Y, v.Height])
152           for (int i = 0; i < Cube.DSize.Length; i++)
153           {
154             Point pt = v.Location + Cube.DSize[i];
155             if (pt.X < 0 || pt.Y < 0 || pt.X >= Cube.Size || pt.Y >= Cube.Size) continue;
156             int height = Cube.GetLevel(v.Height, i);
157             int width = v.Width + cube.GetBottom(height);
158             if (dist[pt.X, pt.Y, height] <= width) continue;
159             dist[pt.X, pt.Y, height] = width;
160             prev[pt.X, pt.Y, height] = v;
161             q.Push(new Rectangle(pt.X, pt.Y, width, height));
162           }
163       return GetPath(prev, start, end, v.Height, dist[end.X, end.Y, v.Height]);
164     }
165     
166     Point[] GetPath(Rectangle[,,] prev, Point start, Point end, int id, int len)
167     {
168       Stack<Point> path = new Stack<Point>();
169       for (Rectangle v = new Rectangle(end.X, end.Y, 0, id);
170         v.Location != start || v.Height != 0;
171         v = prev[v.X, v.Y, v.Height]) path.Push(v.Location);
172       path.Push(start);
173       path.Push(new Point(len, 0));
174       return path.ToArray();
175     }
176     
177     int[,,] GetDistance()
178     {
179       int[,,] dist = new int[Cube.Size, Cube.Size, Cube.Level];
180       for (int i = 0; i < dist.GetLength(0); i++)
181         for (int j = 0; j < dist.GetLength(1); j++)
182           for (int k = 0; k < dist.GetLength(2); k++)
183             dist[i, j, k] = int.MaxValue; // infinity
184       return dist;
185     }
186     
187     Point GetPosition(string s)
188     {
189       return new Point(s[0- 'a', s[1- '1');
190     }
191     
192     string PutPosition(Point pt)
193     {
194       return string.Format(" {0}{1}", (char)(pt.X + 'a'), pt.Y + 1);
195     }
196   }
197 }


返回目录
posted on 2009-02-28 20:25  银河  阅读(2712)  评论(0编辑  收藏  举报