/*
* A* - Wikipedia
* http://j...content-available-to-author-only...a.org/wiki/A*
*
* A*探索アルゴリズムの再現
*
*/
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
{
Scanner sc
= new Scanner
(System.
in); final int w = sc.nextInt();
final int h = sc.nextInt();
Node start = null;
Node goal = null;
int[][] map = new int[h][w];
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
int f = sc.nextInt();
if (f < 3)
{
if (f == 1)
{
start = new Node(x, y);
}
else if (f == 2)
{
goal = new Node(x, y);
}
map[y][x] = 0;
}
else
{
map[y][x] = 3;
}
}
}
if (start
== null || goal
== null) throw new Exception("input error");
HashMap<Node, Node> open = new HashMap<Node, Node>();
HashMap<Node, Node> close = new HashMap<Node, Node>();
start.setFStar(distance(start, goal));
open.put(start, start);
for (;;)
{
Node minf = null;
for (Node node : open.values())
{
if (minf != null)
{
if (node.getFStar() >= minf.getFStar())
{
continue;
}
}
minf = node;
}
if (minf == null)
{
}
if (goal.equals(minf))
{
break;
}
open.remove(minf);
close.put(minf, minf);
HashSet<Node> ms = new HashSet<Node>();
for (int dy = -1; dy <= 1; dy++)
{
for (int dx = -1; dx <= 1; dx++)
{
if ((dx != 0 && dy != 0) || (dx == dy)) continue;
int tx = dx + minf.x;
int ty = dy + minf.y;
if (tx < 0 || tx >= w || ty < 0 || ty >= h) continue;
if (map[ty][tx] != 0) continue;
Node m = new Node(tx, ty);
ms.add(m);
}
}
double hstarN = distance(minf, goal);
double gstarN = minf.getFStar() - hstarN;
double cost = 1;
for (Node m : ms)
{
double hstarM = distance(m, goal);
double fdashM = gstarN + hstarM + cost;
m.setFStar(fdashM);
m.setParent(minf);
if (open.containsKey(m))
{
if (fdashM < open.get(m).getFStar())
{
open.put(m, m);
}
}
else if (close.containsKey(m))
{
if (fdashM < close.get(m).getFStar())
{
open.put(m, m);
close.remove(m);
}
}
else
{
open.put(m, m);
}
}
}
Node t = open.get(goal);
while (!start.equals(t) && t != null)
{
map[t.y][t.x] = 7;
t = t.getParent();
}
map[start.y][start.x] = 1;
map[goal.y][goal.x] = 2;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
System.
out.
print(map
[y
][x
] + " "); }
}
}
static double distance(Node n1, Node n2)
{
double x = (double)(n1.x - n2.x);
double y = (double)(n1.y - n2.y);
return Math.
sqrt(x
* x
+ y
* y
); }
static class Node
{
public final int x;
public final int y;
private Node parent = null;
private double fstar = 0;
Node(int x, int y)
{
this.x = x;
this.y = y;
}
void setFStar(double fstar)
{
this.fstar = fstar;
}
double getFStar()
{
return this.fstar;
}
void setParent(Node parent)
{
this.parent = parent;
}
Node getParent()
{
return this.parent;
}
@Override
public int hashCode()
{
return this.x ^ this.y;
}
@Override
public boolean equals
(Object obj
) {
if (obj == this) return true;
if (obj == null) return false;
if (!this.getClass().equals(obj.getClass())) return false;
Node node = (Node)obj;
return this.x == node.x && this.y == node.y;
}
}
}