【问题标题】:C# Finding largest connected area of adjacent empty cells (string[,])C#查找相邻空单元格的最大连接区域(字符串[,])
【发布时间】:2014-11-03 05:24:09
【问题描述】:

我正在尝试找到相邻空单元格的最大连接区域(对角连接计数)。

例如,如果我有一个这样的矩阵(“”-Empty,“F”-Filled)

{" "," "," ","F"},
{"F","F","F"," "},
{" "," ","F"," "}

结果应该是:

{"*","*","*","F"},
{"F","F","F","*"},
{" "," ","F","*"}

除了旧的 BFS/DFS 之外还有其他想法吗?

这是我的工作代码(通过 BFS 解决):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _09.LargestConnectedArea
{
    class Program
    {
        public static string[,] matrix;
        public static int mRow, mCol;

        public static void Input(string mode = "mid")
        {
            if (mode.Equals("top"))
            {
                matrix = new string[4, 4]{
                {" "," "," "," "},
                {" "," "," "," "},
                {"F"," "," ","F"},
                {" ","F","F"," "}
                };
                mRow = matrix.GetLength(1);
                mCol = matrix.GetLength(0);
            }
            else if (mode.Equals("mid"))
            {
                matrix = new string[4, 4]{
                {"F","F","F"," "},
                {" "," "," "," "},
                {"F"," "," ","F"},
                {"F","F","F","F"}
                };
                mRow = matrix.GetLength(1);
                mCol = matrix.GetLength(0);
            }
            else if (mode == "test")
            {
                // matrix = new string[4, 4];
                matrix = new string[7, 4]{
                {" ","F","F"," "},
                {"F","F"," "," "},
                {" "," "," ","F"},
                {"F","F"," "," "},
                {" ","F"," ","F"},
                {" ","F"," ","F"},
                {" ","F"," ","F"}
                };
                mRow = 7;
                mCol = 4;
            }
            else
            {
                Console.Write("maxrow: ");
                mRow = int.Parse(Console.ReadLine());
                Console.Write("maxcol: ");
                mCol = int.Parse(Console.ReadLine());
                matrix = new string[mRow, mCol];
                for (int row = 0; row < mRow; row++)
                {
                    Console.WriteLine();
                    Console.WriteLine("Row {0}:", row);
                    Console.WriteLine();
                    for (int col = 0; col < mCol; col++)
                    {
                        Console.Write("Element {0}:", col);
                        matrix[row, col] = Console.ReadLine();
                    }
                }
            }
        }

        public static int BFS(Stack<Tuple<int, int>> currPath, string symbol = "*", int counter = 0)
        {
            if (currPath.Count == 0)
            {
                return counter;
            }
            else
            {
                ;
                Tuple<int, int> top = new Tuple<int, int>(currPath.Peek().Item1, currPath.Pop().Item2);
                matrix[top.Item1, top.Item2] = symbol;
                counter++;
                //top TEST: PASSED
                #region
                if (top.Item1 > 0)
                {
                    //_X_
                    if (matrix[top.Item1 - 1, top.Item2].Equals(" "))
                    {
                        matrix[top.Item1 - 1, top.Item2] = symbol;
                        currPath.Push(new Tuple<int, int>(top.Item1 - 1, top.Item2));
                    }
                    //X__
                    if (top.Item2 > 0)
                    {
                        if (matrix[top.Item1 - 1, top.Item2 - 1].Equals(" "))
                        {
                            matrix[top.Item1 - 1, top.Item2 - 1] = symbol;
                            currPath.Push(new Tuple<int, int>(top.Item1 - 1, top.Item2 - 1));
                        }
                    }
                    //__X
                    if (top.Item2 < mCol - 1)
                    {
                        if (matrix[top.Item1 - 1, top.Item2 + 1].Equals(" "))
                        {
                            matrix[top.Item1 - 1, top.Item2 + 1] = symbol;
                            currPath.Push(new Tuple<int, int>(top.Item1 - 1, top.Item2 + 1));
                        }
                    }
                }
                #endregion
                //mid TEST: PASSED
                #region
                if (top.Item2 > 0)
                {
                    if (matrix[top.Item1, top.Item2 - 1].Equals(" "))
                    {
                        matrix[top.Item1, top.Item2 - 1] = symbol;
                        currPath.Push(new Tuple<int, int>(top.Item1, top.Item2 - 1));
                    }
                }
                if (top.Item2 < mCol - 1)
                {
                    if (matrix[top.Item1, top.Item2 + 1].Equals(" "))
                    {
                        matrix[top.Item1, top.Item2 + 1] = symbol;
                        currPath.Push(new Tuple<int, int>(top.Item1, top.Item2 + 1));
                    }
                }
                #endregion
                //bot TEST: PASSED
                #region
                if (top.Item1 < mRow - 1)
                {
                    //_X_
                    if (matrix[top.Item1 + 1, top.Item2].Equals(" "))
                    {
                        matrix[top.Item1 + 1, top.Item2] = symbol;
                        currPath.Push(new Tuple<int, int>(top.Item1 + 1, top.Item2));
                    }
                    //X__
                    if (top.Item2 > 0)
                    {
                        if (matrix[top.Item1 + 1, top.Item2 - 1].Equals(" "))
                        {
                            matrix[top.Item1 + 1, top.Item2 - 1] = symbol;
                            currPath.Push(new Tuple<int, int>(top.Item1 + 1, top.Item2 - 1));
                        }
                    }
                    //__X
                    if (top.Item2 < mCol - 1)
                    {
                        if (matrix[top.Item1 + 1, top.Item2 + 1].Equals(" "))
                        {
                            matrix[top.Item1 + 1, top.Item2 + 1] = symbol;
                            currPath.Push(new Tuple<int, int>(top.Item1 + 1, top.Item2 + 1));
                        }
                    }
                }
                #endregion

                return BFS(currPath, symbol, counter);
            }
        }

        public static void Print(string[,] a)
        {
            for (int row = 0; row < mRow; row++)
            {
                for (int col = 0; col < mCol; col++)
                {
                    Console.Write("\'{0}\' ", a[row, col]);
                }
                Console.WriteLine();
            }
            Console.WriteLine();
        }

        static void Main(string[] args)
        {

            Input("test");
            Print(matrix);

            List<Tuple<char, int>> areaCalculated = new List<Tuple<char, int>>();

            char symbol = '1';

            //Console.WriteLine(BFS(a, symbol + ""));

            for (int row = 0; row < mRow; row++)
            {
                for (int col = 0; col < mCol; col++)
                {
                    if (matrix[row, col].Equals(" ") == true)
                    {
                        Stack<Tuple<int, int>> a = new Stack<Tuple<int, int>>();
                        a.Push(new Tuple<int, int>(row, col));

                        areaCalculated.Add(new Tuple<char, int>(symbol, BFS(a, symbol + "")));
                        symbol++;
                    }
                }
            }

            areaCalculated.Sort((x, y) => y.Item2.CompareTo(x.Item2));

            Print(matrix);

            Console.WriteLine("The largest connected area of adjacent empty cells(diagonal connection counts) is marked with the \'"+areaCalculated.ElementAt(0).Item1 + "\' symbol and contains " + areaCalculated.ElementAt(0).Item2 + " cells.");
            // Console.WriteLine(areaCalculated.ElementAt(areaCalculated.Count - 1).Item1 + " " + areaCalculated.ElementAt(areaCalculated.Count - 1).Item2);
        }
    }
}

【问题讨论】:

  • 定义相邻。您是指仅在同一行中的相邻单元格,还是包含列?您的结果表明相邻包括对角线,因为最后两行的最后一列带有 *
  • 然后发布您的代码,或者至少几行关于您的尝试如何解决它的描述。如果您的解决方案有效,那么这似乎更适合 codereview.stackexchange.com
  • 相邻的意思是单元格至少有一个共同的边缘/边。很抱歉在这里发布这个(我是stackoverflow的新手)。也许你是对的,也许是为了代码审查。我在这里发布它的原因只是为了收集一些新的想法,也许是为了找到比我更好的解决方案。附言我将编辑问题并发布代码。 :)
  • 这个问题似乎是题外话,因为它属于codereview.stackexchange.com
  • 为了标记整个连接区域,我建议查看 Flood Fill 算法及其分析,以优化(按常数,而不是数量级)运行时间 - en.wikipedia.org/wiki/Flood_fill。除此之外,它会根据您获得的实际输入类型变得非常具体

标签: c# string matrix area


【解决方案1】:

感谢练习,这是我的尝试

var wspace = new List<Tuple<int, int>>();
string[,] cells = { 
    { "F", " ", "F", "F", "F", "F", " " }, 
    { "F", "F", "F", " ", "F", "F", " " }, 
    { "F", " ", "F", " ", "F", " ", "F" },
    { "F", "F", " ", "F", "F", " ", "F" },
    { "F", " ", "F", " ", "F", " ", "F" }
};

for (int i = 0; i < cells.GetLength(0); i++)
    for (int j = 0; j < cells.GetLength(1); j++)
        if (cells[i, j] == " ")
            wspace.Add(new Tuple<int, int>(i, j));

var region = new List<Tuple<int, int>>();
var pre = new List<Tuple<int, int>>();
var regions = new List<List<Tuple<int, int>>>();
region.Add(wspace.First());
wspace = wspace.Skip(1).ToList();

for(int z=0; z<wspace.Count(); z++)
{
    var pos = wspace[z];
    bool keep = true;
    for (int i = -1; i < 2 && keep; i++)
    {
        for (int j = -1; j < 2 && keep; j++)
        {
            if (region.Any(x => x.Item1 == (pos.Item1 + i) && x.Item2 == (pos.Item2 + j)))
            {
                pre.Reverse();
                wspace.AddRange(pre);
                pre.Clear();
                region.Add(pos);
                keep = false;
            }
        }
    }

    if (keep && (pos.Item1 > region.Last().Item1) && (pos.Item2 > region.Last().Item2))
    {
        regions.Add(region.ToList());
        region.Clear();
        region.Add(pos);
    }
    else if (keep) pre.Add(pos);

}
regions.Add(region);
region = regions.OrderBy(x => x.Count).Last().OrderBy(s => s.Item1 * cells.GetLength(1) + s.Item2).ToList();

region.ForEach(x => Console.WriteLine("Array: {0} Key: {1}", x.Item1 + 1, x.Item2 + 1));

到目前为止效果很好,请尝试告诉我

实际输出

Array: 2 Key: 4
Array: 3 Key: 2
Array: 3 Key: 4
Array: 4 Key: 3
Array: 5 Key: 2
Array: 5 Key: 4

【讨论】:

  • 我会 ^^ 明天我会告诉你,因为我今天测试它已经筋疲力尽了......我也会在顶部发布我的解决方案,也请随意看看并告诉我是否可以优化某些东西^^
  • 试图理解你的输出。您的示例的最大连接区域具有 10 个单元的三个解决方案。其中一个是系列:[2,0][2,1][3,1][3,2][2,3][3,4][3,5][2,5][1,6][0,6]
  • @Rufus 你能用实际的代码试试吗?我想我都修好了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
相关资源
最近更新 更多