Java 将二维矩阵转换为图形

Java 将二维矩阵转换为图形,java,algorithm,graph,Java,Algorithm,Graph,将包含无效点和有效点的给定2D矩阵转换为仅包含有效节点的图形时,我面临一个问题。问题是这样的。 我有一个2D矩阵,比如 # # # # # # . C C # # S # # # # . . E # # # # # # 我想找到从S到E的最短距离,记住我必须覆盖所有的“C”和“#”作为墙,“.”作为自由路径。 现在我想把这个矩阵转换成一个只包含有效节点的图。 请帮帮我 n = number of nodes for i=1 to n: for j=1 to n: d[i][j]=INF f

将包含无效点和有效点的给定2D矩阵转换为仅包含有效节点的图形时,我面临一个问题。问题是这样的。 我有一个2D矩阵,比如

# # # # #
# . C C #
# S # # #
# . . E #
# # # # # 
我想找到从S到E的最短距离,记住我必须覆盖所有的“C”和“#”作为墙,“.”作为自由路径。 现在我想把这个矩阵转换成一个只包含有效节点的图。 请帮帮我

n = number of nodes
for i=1 to n: for j=1 to n: d[i][j]=INF
 for k=1 to n:
   for i=1 to n:
    for j=1 to n:
        d[i][j] = min(d[i][j], d[i][k] + d[k][j])

shortest = INF
for each permutation a[1],a[2],...a[k] of the 'mustpass' nodes:
  shortest = min(shortest, d['start'][a[1]]+d[a[1]][a[2]]+...+d[a[k]]['end'])
print shortest

我要么创建一个节点结构,要么创建一个节点类。例如:

struct Node {
    node type;  //Indicate in some way if the node is a 'S', '.' or 'E'
    std::vector<Node> adjacentNodes;
}

为了生成图形,必须为每个非墙空间生成一个节点。遍历2D矩阵(假设它只是一个字符数组),创建节点并添加边:

nodes = new Node[matrix.length][matrix[0].length]; //instance variable

for ( int row = 0; row < matrix.length; row++ )
{
  for ( int col = 0; col < matrix[row].length; col++ )
  {
    char type = matrix[row][col];
    if ( type != '#' )
    {
      Node n = new Node();
      nodes[row][col] = n; //constructor to determine type of node
      if ( type == 'S' )
        startNode = n;
      else if ( type == 'E' )
        endNode = n;

      findNeighbors(row, col); //assuming nodes and matrix variables are instance variables
    }
    else
      nodes[row][col] = null;
  }
}
nodes=新节点[matrix.length][matrix[0.length]//实例变量
对于(int row=0;row
使用2D节点阵列,您可以使用FindNeighbor遍历并添加邻居:

public void findNeighbors(int row, int col)
{
  for ( int r = -1; r <= 1; r++ )
  {
    for ( int c = -1; c <= 1; c++ )
    {
      try { 
        if ( matrix[row+r][col+c] != '#' ) 
          nodes[row][col].addEdge(nodes[row+r][col+c]);
      } catch (ArrayIndexOutOfBoundsException e) {}
    }
  }
}
public void findNeighbors(整数行,整数列)
{

对于(int r=-1;r而言,字符的2d矩阵是这个问题的完美图形表示

每个矩阵元素(i,j)都是一个节点。假设您只能向东、西、北、南移动,则从该节点到其相邻节点(i+或-1,j+或-1)存在0到4条无向边,只要在每个位置测试字符即可确定

您也可以测试超出范围(负值或太大)的i,j值,但如果如您所示,边界周围总是有一道“墙”,则不需要这样做。这道墙可作为一道墙


构建一个通用结构来表示嵌入在网格中的图形是浪费时间和内存的。

这看起来像是一个家庭作业,但为了对话(时间/空间复杂性),我会做一些不同的事情。首先,我会创建一个只包含节点之间有效边的图形,这些边可以是路径(例如,不是墙)。这将最小化所需的空间。我不会使用矩阵,因为它在实图(稀疏)中使用了太多的空间,并且时间复杂度为ROW*COL(对于平方矩阵,V^2)

类图{
地图边缘;
图(){
this.edgeTo=新HashMap();
}
公共整数大小(){
返回边缘到.size();
}
公共无效补遗(整数v1,整数v2){
添加(v1,v2);
添加(v2,v1);
}
专用void add(int-from,int-to){
如果(!edgeTo.CONTANSKEY(从)){
Set s=新的HashSet();
s、 增加(至);
边缘放置(从,s);
}否则{
edgeTo.get(from).add(to);
}
}
公共集调整(整数v){
返回边缘到。获取(v);
}
}
有了它,图表的创建就遵循了前一篇文章的思路

    private Graph createGrap(char[][] matrix) {
    Graph g = new Graph();
    for (int r = 0; r < matrix.length; r++) {
        for (int c = 0; c < matrix[0].length; c++) {

            // skip this cells
            if (!isFreeCell(matrix[r][c])) {
                continue;
            }

            int id = createUniqueId(r, c);
            if (matrix[r][c] == 'S') {
                startVertex = id;
            } else if (matrix[r][c] == 'E') {
                endVertex = id;
            }
            createNeighbor(r, c, matrix, g);
        }
    }
    return g;
}

private void createNeighbor(final int r, final int c, final char[][] matrix2, final Graph g) {
    for (int row = -1; row <= 1; row++) {
        for (int col = -1; col <= 1; col++) {
            // avoid the center cell
            if (row ==0 && col == 0){
                continue;
            }
            // outside matrix
            if ((0 > c + col) || (c + col >= matrix2[0].length) || (0 > r + row) || (r + row >= matrix2.length)) {
                continue;
            }
            char value = matrix2[r+row][c+col];
            if (!isFreeCell(value)){
                continue;
            }
            int from = createUniqueId(r, c);
            int to = createUniqueId(row+r, col+c);
            g.add(from, to);
        }
    }

}

private boolean isFreeCell(char value) {
    return (value != '#' && value !='C');
}

private int createUniqueId(int r, int c) {
    return r * MAX_COL + c;
}
private Graph createGrap(char[][]矩阵){
图g=新图();
对于(int r=0;rr+row)| |(r+row>=matrix2.length)){
继续;
}
字符值=矩阵2[r+行][c+列];
如果(!isFreeCell(值)){
继续;
}
int from=createUniqueId(r,c);
int to=createUniqueId(行+r,列+c);
g、 增加(从,到);
}
}
}
私有布尔值isFreeCell(字符值){
返回值(value!='#'&&value!='C');
}
私有int createUniqueId(int r,int c){
返回r*MAX_COL+c;
}
现在唯一剩下的就是找到最短路径…使用这个没有负加权边的无向图的BFS

private void findSP(Graph g) {
    if (g == null || g.size() == 0) {
        throw new IllegalArgumentException("empty or null graph");
    }

    if (g.size() == 1) {
        throw new IllegalArgumentException(
                "graph's size must be greater than 1");
    }

    if (startVertex == -1) {
        throw new IllegalArgumentException("Start vertex not found");
    }

    if (endVertex == -1) {
        throw new IllegalArgumentException("End vertex not found");
    }

    Map<Integer, Integer> sonToParent = bfs(g, startVertex, endVertex);

    Stack<Integer> path = new Stack<Integer>();
    for (int son = endVertex; son!= startVertex; son = sonToParent.get(son)){
        path.push(son);
    }

    path.push(startVertex);
    while (!path.isEmpty()){
        System.out.print(path.pop() + ", ");
    }
}

private Map<Integer, Integer> bfs(Graph g, int startVertex2, int endVertex2) {
    Queue<Integer> q = new LinkedList<Integer>();
    Set<Integer> marked = new HashSet<Integer>();
    Map<Integer, Integer> sonToParent = new HashMap<Integer, Integer>();
    q.add(startVertex2);
    while (!q.isEmpty()) {
        int v = q.poll();
        for (Integer s : g.adj(v)) {
            if (!marked.contains(s)) {
                marked.add(s);
                sonToParent.put(s, v);

                if (s == endVertex2) {
                    return sonToParent;
                }

                q.add(s);
            }
        }

    }
    return null;
}
私有void findSP(图g){
如果(g==null | | g.size()==0){
抛出新的IllegalArgumentException(“空或空图形”);
}
如果(g.size()==1){
抛出新的IllegalArgumentException(
“图表的大小必须大于1”);
}
如果(startVertex==-1){
抛出新的IllegalArgumentException(“未找到起始顶点”);
}
如果(endVertex==-1){
抛出新的IllegalArgumentException(“未找到结束顶点”);
}
映射sonToParent=bfs(g,startVertex,endVertex);
堆栈路径=新堆栈();
for(int-son=endVertex;son!=startVertex;son=sonToParent.get(son)){
推(子);
}
路径推送(startVertex);
而(!path.isEmpty()){
System.out.print(path.pop()+“,”);
}
}
私有映射bfs(图g,int startVertex2,int endVertex2){
队列q=新的LinkedList();
Set marked=新的HashSet();
Map sonToParent=new HashMap();
q、 添加(startVertex2);
而(!q.isEmpty()){
int v=q.poll();
对于(整数s:g.adj(v)){
如果(!marked.contains)){
标记。添加(s);
sonToParent.put(s,v);
如果(s==endVertex2){
返回sonToParent;
}
q、 添加(s);
}
}
}
返回null;
}

我正试图用Java来做这件事。还没有赶上进度吗
    private Graph createGrap(char[][] matrix) {
    Graph g = new Graph();
    for (int r = 0; r < matrix.length; r++) {
        for (int c = 0; c < matrix[0].length; c++) {

            // skip this cells
            if (!isFreeCell(matrix[r][c])) {
                continue;
            }

            int id = createUniqueId(r, c);
            if (matrix[r][c] == 'S') {
                startVertex = id;
            } else if (matrix[r][c] == 'E') {
                endVertex = id;
            }
            createNeighbor(r, c, matrix, g);
        }
    }
    return g;
}

private void createNeighbor(final int r, final int c, final char[][] matrix2, final Graph g) {
    for (int row = -1; row <= 1; row++) {
        for (int col = -1; col <= 1; col++) {
            // avoid the center cell
            if (row ==0 && col == 0){
                continue;
            }
            // outside matrix
            if ((0 > c + col) || (c + col >= matrix2[0].length) || (0 > r + row) || (r + row >= matrix2.length)) {
                continue;
            }
            char value = matrix2[r+row][c+col];
            if (!isFreeCell(value)){
                continue;
            }
            int from = createUniqueId(r, c);
            int to = createUniqueId(row+r, col+c);
            g.add(from, to);
        }
    }

}

private boolean isFreeCell(char value) {
    return (value != '#' && value !='C');
}

private int createUniqueId(int r, int c) {
    return r * MAX_COL + c;
}
private void findSP(Graph g) {
    if (g == null || g.size() == 0) {
        throw new IllegalArgumentException("empty or null graph");
    }

    if (g.size() == 1) {
        throw new IllegalArgumentException(
                "graph's size must be greater than 1");
    }

    if (startVertex == -1) {
        throw new IllegalArgumentException("Start vertex not found");
    }

    if (endVertex == -1) {
        throw new IllegalArgumentException("End vertex not found");
    }

    Map<Integer, Integer> sonToParent = bfs(g, startVertex, endVertex);

    Stack<Integer> path = new Stack<Integer>();
    for (int son = endVertex; son!= startVertex; son = sonToParent.get(son)){
        path.push(son);
    }

    path.push(startVertex);
    while (!path.isEmpty()){
        System.out.print(path.pop() + ", ");
    }
}

private Map<Integer, Integer> bfs(Graph g, int startVertex2, int endVertex2) {
    Queue<Integer> q = new LinkedList<Integer>();
    Set<Integer> marked = new HashSet<Integer>();
    Map<Integer, Integer> sonToParent = new HashMap<Integer, Integer>();
    q.add(startVertex2);
    while (!q.isEmpty()) {
        int v = q.poll();
        for (Integer s : g.adj(v)) {
            if (!marked.contains(s)) {
                marked.add(s);
                sonToParent.put(s, v);

                if (s == endVertex2) {
                    return sonToParent;
                }

                q.add(s);
            }
        }

    }
    return null;
}