我有一个代表网格的2D数组/矩阵。当元素在特定位置添加到网格时,矩阵等效位置用1填充(所以没有任何东西,有0)。
我应该如何检查网格上的元素是否形成循环? (他们不能以对角线连接)。
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 1 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
这是一个例子,元素会移动。
感谢您的帮助
答案 0 :(得分:1)
看看Flood Fill。您可以在维基百科页面上找到伪代码。 有关此算法的完整示例,请查看Rosetta Code上的java实现。
您的设计的一般想法是:
答案 1 :(得分:1)
作为jkeuhlen的洪水填充解决方案的替代方案,你可以通过矩阵使用类似的东西来寻找循环:
for(int r = 1; r < intArray.length-1; r++)
for (int c = 1; c < intArray[0].length-1; c++)
if (intArray[r][c] == 1)
continue;
else if (intArray[r-1][c-1] == 1 && intArray[r-1][c] == 1 && intArray[r-1][c+1] == 1 && intArray[r][c-1] == 1 &&
intArray[r][c+1] == 1 && intArray[r+1][c-1] == 1 && intArray[r+1][c] == 1 && intArray[r+1][c+1] == 1)
System.out.println("("+r+", "+c+")");
可能更适合这种情况。
答案 2 :(得分:1)
因为今天是比萨饼日,我会在评论中提供一些关于回溯的信息。
回溯的想法基本上是假设每个选项都有效,直到相反的证明。
在最坏的情况下,你正在检查每条路径(不是每个字段!),只是为了弄清楚,没有循环。
你开始“1”并不重要。
因此,基本算法可以这样写(伪代码):
private boolean testSolution(Position p, Position prior, List<Position> visited){
//return true, if our current Position solves the problem
if (visited.contains(p)){
return true;
}
//this is now visited
visited.add(p);
//Else: Check, which options we have at the current position
//and check if one of the neighbors is a valid solution.
for (Position nextP : getNeighborsOf(p)){
if (prior == null || !nextP.equals(prior)){
if (testSolution(nextP, p, visited)){
//this satisfies the condition!
//we hit a position we visited a while ago but not exactly in
//the prior step. -> theres at least one loop.
return true;
}else{
//check next neighbor for the current position
// (no code required)
}
}else{
//moving back would end in an infinite loop. avoid that.
// (no code required)
}
}
//no neighbor working? return false to return to the "prior"
//position, so it can evaluate other options.
return false;
}
这样调用:
if (testSolution(firstOneInTheGrid, null, new LinkedList<Position>())){
//theres a loop
}else{
//no loop found.
}
编辑:因为Pizza很好吃,我想检查一下我的解释是否正常 - 它可以工作(必须添加grid参数一次运行多个测试,如果只有一个网格,访问可能是静态/实例绑定)
public class Main {
private static int[][] t1 = {
{0,1,1,0},
{0,1,1,0},
{0,0,0,0},
{0,0,0,0}
};
private static int[][] t2 = {
{0,0,0,0},
{0,1,1,1},
{0,1,0,1},
{0,1,1,1}
};
private static int[][] t3 = {
{1,1,1,1},
{1,0,0,1},
{1,0,0,1},
{1,1,1,1}
};
private static int[][] t4 = {
{1,1,0,1},
{0,1,0,1},
{0,1,0,1},
{1,1,1,1}
};
protected static class Position{
public int x;
public int y;
public Position(int x, int y){
this.x=x;
this.y=y;
}
@Override
public String toString() {
return "Position [x=" + x + ", y=" + y + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Position other = (Position) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
public static void main(String[] argv) {
test("t1", t1, new Position(1,0)); //static start position
test("t2", t2, new Position(1,1)); //static start position
test("t3", t3, new Position(0,0)); //static start position
test("t4", t4, new Position(0,0)); //static start position
}
public static void test(String name, int[][] arr, Position start){
System.out.println("Testing case " + name);
if (testSolution(start, null, new LinkedList<Position>(), arr)){
System.out.println("Loop Found!");
}else{
System.out.println("No Loop.");
}
}
public static boolean testSolution(Position p,Position prior, List<Position> visited, int[][] grid){
System.out.println("Current: " +p);
if (visited.contains(p))
return true;
visited.add(p);
for (Position nextP : getNeighbors(p, grid)) {
if (prior == null || !nextP.equals(prior)){
if (testSolution(nextP, p, visited, grid)){
return true;
}
}
}
return false;
}
public static List<Position> getNeighbors(Position p, int[][] grid){
//Upper bound 3 hardcoded, could be dynamic.
List<Position> result = new LinkedList<Position>();
if (p.x > 0){ //left position
Position np =new Position(p.x-1,p.y);
if (grid[np.y][np.x]== 1)
result.add(np);
}
if (p.x < 3){ //right position
Position np =new Position(p.x+1,p.y);
if (grid[np.y][np.x]== 1)
result.add(np);
}
if (p.y > 0){ //top position
Position np =new Position(p.x,p.y-1);
if (grid[np.y][np.x]== 1)
result.add(np);
}
if (p.y < 3){ //bottom position
Position np =new Position(p.x,p.y+1);
if (grid[np.y][np.x]== 1)
result.add(np);
}
return result;
}
}
结果:
Testing case t1
Current: Position [x=1, y=0]
Current: Position [x=2, y=0]
Current: Position [x=2, y=1]
Current: Position [x=1, y=1]
Current: Position [x=1, y=0]
Loop Found!
Testing case t2
Current: Position [x=1, y=1]
Current: Position [x=2, y=1]
Current: Position [x=3, y=1]
Current: Position [x=3, y=2]
Current: Position [x=3, y=3]
Current: Position [x=2, y=3]
Current: Position [x=1, y=3]
Current: Position [x=1, y=2]
Current: Position [x=1, y=1]
Loop Found!
Testing case t3
Current: Position [x=0, y=0]
Current: Position [x=1, y=0]
Current: Position [x=2, y=0]
Current: Position [x=3, y=0]
Current: Position [x=3, y=1]
Current: Position [x=3, y=2]
Current: Position [x=3, y=3]
Current: Position [x=2, y=3]
Current: Position [x=1, y=3]
Current: Position [x=0, y=3]
Current: Position [x=0, y=2]
Current: Position [x=0, y=1]
Current: Position [x=0, y=0]
Loop Found!
Testing case t4
Current: Position [x=0, y=0]
Current: Position [x=1, y=0]
Current: Position [x=1, y=1]
Current: Position [x=1, y=2]
Current: Position [x=1, y=3]
Current: Position [x=0, y=3]
Current: Position [x=2, y=3]
Current: Position [x=3, y=3]
Current: Position [x=3, y=2]
Current: Position [x=3, y=1]
Current: Position [x=3, y=0]
No Loop.
该死的,现在我提供了一个解决我的评论的方法。
针对暴力的优势:未选中“0”字段。因此,如果您正在搜索2x2循环时间复杂度保持不变,无论是2x2矩阵还是500Mx500M(搜索任何 1除外)
注意:这假设所有“1”都已连接,所以不是这样的:
1 0 0 0
0 0 1 1
0 0 1 1
0 0 0 0
但您也可以通过检查是否所有“1”字段至少评估过一次来覆盖这一点。 - 否则开始对尚未评估的“1”进行另一次搜索。