using System; using System.Collections.Generic; using System.IO; using System.Linq; class Vertex : Tuple { public Vertex(int item1, int item2) : base(item1, item2) { } static Vertex() { Edges = new Dictionary>(); } public int X { get { return Item1; } } public int Y { get { return Item2; } } public static Dictionary> Edges { get; private set; } internal bool IsOnBoard(int boardSize) { return X >= 0 && Y >= 0 && X < boardSize && Y < boardSize; } } class Solution { static void Main(String[] args) { int n = Convert.ToInt32(Console.ReadLine()); // your code goes here var result = new int[n + 1, n + 1]; for (int i = 1; i < n; i++) { for (int j = 1; j < n; j++) { var start = new Vertex(0, 0); var current = new Vertex(i, j); var visited = new SortedSet(); visited.Add(start); visited.Add(current); Vertex.Edges.Clear(); Vertex.Edges.Add(start, new SortedSet() { current }); BuildTree(current, visited, current.X, current.Y, n, 1); // Find the shortest path in the graph using Dijkstra var queueSize = n * n; ; var dist = new int[n, n]; var inQueue = new bool[n, n]; for (int k = 0; k < n; k++) { for (int l = 0; l < n; l++) { dist[k, l] = int.MaxValue; inQueue[k, l] = true; } } dist[start.X, start.Y] = 0; while (queueSize >= 0) { var minDist = int.MaxValue; var u = new Vertex(n - 1, n - 1); for (int k = 0; k < n; k++) { for (int l = 0; l < n; l++) { if (inQueue[k, l] && dist[k, l] < minDist) { u = new Vertex(k, l); minDist = dist[k, l]; } } } if (dist[u.X, u.Y] == int.MaxValue) { break; } inQueue[u.X, u.Y] = false; --queueSize; SortedSet edges; if (Vertex.Edges.TryGetValue(u, out edges)) { foreach (var v in edges) { var alt = dist[u.X, u.Y] + 1; if (alt < dist[v.X, v.Y]) { dist[v.X, v.Y] = alt; } } } } result[i, j] = dist[n - 1, n - 1] == int.MaxValue ? -1 : dist[n - 1, n - 1]; Console.Write(result[i, j]); Console.Write(" "); } Console.WriteLine(); } } private static void BuildTree(Vertex current, SortedSet visited, int a, int b, int n, int level) { AddVertex(current, current.X + a, current.Y + b, visited, a, b, n, level + 1); AddVertex(current, current.X - a, current.Y - b, visited, a, b, n, level + 1); AddVertex(current, current.X + a, current.Y - b, visited, a, b, n, level + 1); AddVertex(current, current.X - a, current.Y + b, visited, a, b, n, level + 1); AddVertex(current, current.X + b, current.Y + a, visited, a, b, n, level + 1); AddVertex(current, current.X - b, current.Y - a, visited, a, b, n, level + 1); AddVertex(current, current.X + b, current.Y - a, visited, a, b, n, level + 1); AddVertex(current, current.X - b, current.Y + a, visited, a, b, n, level + 1); } private static void AddVertex(Vertex current, int x2, int y2, SortedSet visited, int a, int b, int n, int level) { var next = new Vertex(x2, y2); if (!next.IsOnBoard(n)) return; SortedSet edges; if (Vertex.Edges.TryGetValue(current, out edges)) { edges.Add(next); } else { edges = new SortedSet() { next }; Vertex.Edges.Add(current, edges); } if (!visited.Contains(next)) { visited.Add(next); BuildTree(next, level == 0 ? new SortedSet() : visited, a, b, n, level + 1); } else if (visited.Contains(next) && !edges.Contains(next)) { edges.Add(next); } } }