Java 将二维矩阵转换为图形
将包含无效点和有效点的给定2D矩阵转换为仅包含有效节点的图形时,我面临一个问题。问题是这样的。 我有一个2D矩阵,比如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
# # # # #
# . 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;
}