2012-06-26 82 views
5

我有以下代码:算法找到矩形

int width = 10; 
int height = 7; 
bool[,] array1 = new bool[width, height]; 


string values = 
    "1100000000" + 
    "1100000011" + 
    "0001100011" + 
    "0001100000" + 
    "0001110000" + 
    "0000000110" + 
    "0000000110"; 

for (int x = 0; x < width; x++) 
{ 
    for (int y = 0; y < height; y++) 
    { 
     array1[x, y] = (values[x + y * width] == '1'); 
    } 
} 

即时寻找一个算法,将提取,我们有一个1

所以从这个数据中我们会得到矩形 范围(0 ,0,2,2), (8,1,2,2), (3,2,3,3), (7,5,2,2) 矩形的顺序并不重要!

但我不知道如何做到这一点任何人有任何指针?

阅读生锈韦伯的回答后,我想出了以下内容:

private static List<Rectangle> GetRectangles(bool[,] array) 
{ 
    List<Rectangle> rectangles = new List<Rectangle>(); 
    for (int x = 0; x < array.GetLength(0); x++) 
    { 
     for (int y = 0; y < array.GetLength(1); y++) 
     { 
      if (array[x, y]) 
      { 
       rectangles.Add(GetRectangle(array, new Point(x, y))); 
      } 
     } 
    } 
    return rectangles; 
} 



static Rectangle GetRectangle(bool[,] array, Point startLocation) 
{ 
    int maxX = int.MinValue; 
    int minX = int.MaxValue; 
    int maxY = int.MinValue; 
    int minY = int.MaxValue; 
    HashSet<Point> visitedLocations = new HashSet<Point>(); 
    Stack<Point> pointsToGo = new Stack<Point>(); 
    Point location; 
    pointsToGo.Push(startLocation); 
    while (pointsToGo.Count > 0) 
    { 
     location = pointsToGo.Pop(); 

     if (!location.X.IsBetween(0, array.GetLength(0) - 1)) 
      continue; 
     if (!location.Y.IsBetween(0, array.GetLength(1) - 1)) 
      continue; 
     if (!array[location.X, location.Y]) 
      continue; 
     if (visitedLocations.Contains(location)) 
      continue; 
     visitedLocations.Add(location); 

     pointsToGo.Push(new Point(location.X + 1, location.Y)); 
     pointsToGo.Push(new Point(location.X, location.Y + 1)); 
     pointsToGo.Push(new Point(location.X - 1, location.Y)); 
     pointsToGo.Push(new Point(location.X, location.Y - 1)); 
    } 

    foreach (Point location2 in visitedLocations) 
    { 
     array[location2.X, location2.Y] = false; 
     if (location2.X > maxX) 
      maxX = location2.X; 
     if (location2.X < minX) 
      minX = location2.X; 
     if (location2.Y > maxY) 
      maxY = location2.Y; 
     if (location2.Y < minY) 
      minY = location2.Y; 
    } 

    return new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1); 
} 

public static bool IsBetween<T>(this T item, T start, T end) 
{ 
    return Comparer<T>.Default.Compare(item, start) >= 0 
     && Comparer<T>.Default.Compare(item, end) <= 0; 
} 
+1

您的值看起来有点偏离。为了得到3,2,3,3,我认为你需要在5,2和5,3的1。我会看看我能为算法提出什么。 – itsme86

+0

实际上不是你的第3个矩形(3,2,2,2)? – kenny

+0

你尝试了什么?当你找到一个块(= 0-> 1或1-> 0转换)时,你只需检查下一行的索引是否匹配。当他们匹配时什么也不做,当不匹配的时候弹出左上角矩形的开始和右下角的最后一行... –

回答

2

COMMENT ::这可能会帮助我回答你的问题,如果你有更好的坐标来定义。 (0,0,2,2)并不完全是笛卡儿,它可能需要一些解释。这是左上角后跟宽度吗?

好的。至少在我看来,最简单的编程方式是从图中提取所有可能的矩形,就是有一个递归定义的方法,在特定的方向搜索对称矩形模式。然而,这可能最终会变得非常缓慢,所以我希望速度不是对你的限制。看看代码的风格,我会说这是一个递归或动态编程的学校作业。

东西沿着以下伪

`

for i in width 
{ 
for j in height 
{ 
if(point[i,j] == 1) 
{ 
     potentials = searh_in_direction(i,j,graph,width,height,RIGHT,[[i,j]]) 
    listOfAllRects.append(potentials) 
} 
} 
} 
list_of_rectangle searh_in_direction(i,j,graph,width,height,direction, listofpoints) 
{ 
    nextdirection = direction.nextdirection; //Right -> down -> left-> up 


    //DEVELOP METHOD FOR RECURSION HERE THAT RETURNS ALL SETS OF 4 POINTS THAT 
    for every point in the direction of travel 
    if the point is the origional point and we have 4 points including the point we are looking at, we have a rectangle and we need to return 
    if point on direction of travel is a one travel on the next direction 
    posiblerects.append(searh_in_direction(i,j,graph,width,height,nextdirection , listofpoints.append(currentpoint))) 

//after all points in direction have bee searched 
return posiblerects. 
} 

`

我知道这个代码可以是非常混乱的线,但是这是你所需要的递归要点元件。 我也会注意到,我已经可以在这段代码中看到一些错误,但是我已经用完了15分钟,我说我将花费在这篇文章上,所以你可能必须自己挑选它们。

+0

对不起,(x,y,宽度,高度)和数组是0的! – Peter

+4

我已经回答了您对主要问题的评论。在收获一堆downvotes之前,您可能需要删除该答案。 – hatchet

1

从问题中不清楚您是否真的想要覆盖1的矩形,或者如果您想要包含零的边界体积,但会覆盖所有1,并且只包含相当少量的矩形。

假设你想要矩形覆盖1的,而你并不需要一个完美的解决方案:

  1. 使数组的临时副本。
  2. 遍历临时找1的
  3. 当你打一个1,开始一个新的rectagle启动为1x1的,偏移到该位置(如仅涉及:1)
  4. 展开矩形向右只要有是下一个单元格中的1
  5. 只要下面的行的1与当前矩形的宽度 相匹配,就将该矩形向下展开。
  6. 一旦你不能向下展开更多的,发射出recgantle,并清除所有从临时
  7. 由矩形覆盖1的继续扫描1的开始与细胞当前矩形的右上角后直接。

这将产生一个像样的覆盖 - 但绝不是理想的。如果你需要一个完美的覆盖物 - 例如保证最小数量的矩形然后它是困难的。

+0

我认为如果你逐个迭代步骤4和5,而不是一次最大化所有,你可能会得到一个稍好的结果 – harold

1

这给了你,你正在寻找相同的结果:

static void Main(string[] args) 
{ 
    string values = 
     "1100000000" + 
     "1100000011" + 
     "0001100011" + 
     "0001100000" + 
     "0001110000" + 
     "0000000110" + 
     "0000000110"; 

    int width = 10; 
    int height = 7; 
    bool[,] array = new bool[width, height]; 

    for (int x = 0; x < width; x++) 
     for (int y = 0; y < height; y++) 
      array[x, y] = (values[x + y * width] == '1'); 

    List<Rectangle> rectangles = new List<Rectangle>(); 

    for (int x = 0; x < width; ++x) 
    { 
     for (int y = 0; y < height; ++y) 
     { 
      if (array[x, y] && !Used(rectangles, x, y)) 
      { 
       int rHeight = 1; 
       for (int rX = x + 1; rX < width && array[rX, y] && !Used(rectangles, rX, y); ++rX) 
        for (int rY = y + 1; rY < height && array[rX, rY] && !Used(rectangles, rX, rY); ++rY) 
         if (rY - y >= rHeight) 
          rHeight = rY - y + 1; 

       int rWidth = 1; 
       for (int rY = y + 1; rY < height && rY - y <= rHeight && array[x, rY] && !Used(rectangles, x, rY); ++rY) 
        for (int rX = x + 1; rX < width && array[rX, rY] && !Used(rectangles, rX, rY); ++rX) 
         if (rX - x >= rWidth) 
          rWidth = rX - x + 1; 

       rectangles.Add(new Rectangle(x, y, rWidth, rHeight)); 
      } 
     } 
    } 

    foreach (Rectangle rect in rectangles) 
     Console.WriteLine(rect); 
} 

private static bool Used(IEnumerable<Rectangle> rectangles, int x, int y) 
{ 
    return rectangles.Any(r => r.Contains(x, y)); 
} 

我做了即席矩形结构,因为我没有引用System.Drawing中,但你可以通过一个System.Drawing.Point来System.Drawing.Rectangle.Contains()并获得相同的结果。

此外,请注意您的阵列的宽度实际上应该是10,你的索引数学是错误的。你应该乘以y的宽度,而不是高度。

+0

感谢您的工作,但我设法找到这些错误,我也设法解决了这个问题,但非常感谢!!! – Peter