首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

C# 兑现枚举所有满足条件的数组

2013-03-19 
C# 实现枚举所有满足条件的数组现有一个 5×15 的数组, 第一列取值在1-15 ,第二列取值 16-30 第三列取值31-

C# 实现枚举所有满足条件的数组
现有一个 5×15 的数组, 第一列取值在1-15 ,第二列取值 16-30 第三列取值31-45 第四列 46-60 第五列取值61-75 ,要求5×15 的数组无重复数字意味着1-75的所有数字都要填充到这个数组里。 现在需要枚举所有满足这个条件的数组,而且要求任何两个数组之间没有相同号码的行。 比如 一个数组第一行为  5,17, 32,49 73 而另外一个数组第10行 也为  5,17,32,49,73 那么就认为后面生成的这个数组是无效的。

请各位高手帮给点意见。如何用C#实现,采用什么算法和数据结构比较好。 C#?算法? 算法 数据结构
[解决办法]
刚看清要枚举所有的,上边的方法就不行了。
要排序了。
算法就是将1-75这些数,填入一个数组,一共多少种填法。
用1于其他数交换;
在用2于其他数交换,
一直到75交换完
因为1于2交换和2与1交换是一样的,所有要去掉重复的
[解决办法]
才这么点数据,用for循环最快,其它都是浪费。
[解决办法]
根据题目的意思,先要做点组合数学的功课来优化最终的算法。
因为要求两个数组实例之间不能有行重复,经过一番考察,发现利用列的取数限制,可以将第一列固定并排序,然后后续的四列进行轮转和组合,这样所有可能的行被遍历并且不会被重复。最后对于15x5,共有15^4个数组。(一开始以为一部分要全排列,后来发现这样既麻烦又反而会引来重复)


using System;
using System.Text;

namespace Perm75
{
    class Program
    {
        /// <summary>
        ///  A class that resolves the matrix puzzle (typically 15x5)
        /// </summary>
        class Perm15X5
        {
            #region Constructors

            /// <summary>
            ///  Creates a Perm puzzle solver by given row and col numbers
            /// </summary>
            /// <param name="rows">The number of rows</param>
            /// <param name="cols">The number of columns</param>
            public Perm15X5(int rows = 15, int cols = 5)
            {
                _rows = rows;
                _cols = cols;
                Init();
            }

            #endregion

            #region Methods

            /// <summary>
            ///  Inits/resets the matrix
            /// </summary>
            private void Init()
            {


                // initializes the data
                _indices = new int[_cols-1][];  // note row/col are transposed in this array
                for (var i = 0; i < _cols-1; i++)
                {
                    _indices[i] = new int[_rows];
                    for (var j = 0; j < _cols; j++)
                    {
                        _indices[i][j] = j;
                    }
                }
                _data = new int[_rows, _cols];

                UpdateData();
            }

            /// <summary>
            ///  Get next matrix
            /// </summary>
            /// <returns>if available</returns>
            public bool GetNext()
            {
                for (var curr = 0; curr < _cols - 1; curr++)
                {
                    for (var i = 0; i < _rows; i++ )
                    {
                        _indices[curr][i] = (_indices[curr][i] + 1) % _rows;
                    }

                    if (_indices[curr][0] != 0)
                    {
                        UpdateData();
                        return true;


                    }
                }

                return false;
            }

            /// <summary>
            ///  Updates display data
            /// </summary>
            private void UpdateData()
            {
                for (var i = 0; i < _cols; i++)
                {
                    var b = i * _rows + 1;
                    for (var j = 0; j < _rows; j++)
                    {
                        // the first row is always in ascending order
                        _data[j, i] = i == 0 ? b + j : b + _indices[i - 1][j];
                    }
                }
            }

            /// <summary>
            ///  Returns its string representation
            /// </summary>
            /// <returns>string representation</returns>
            public override string ToString()
            {
                var sb = new StringBuilder();
                for (var i = 0; i < _cols; i++)
                {
                    sb.AppendFormat("Row {0}: ", i);
                    for (var j = 0; j < _rows; j++)


                    {
                        sb.AppendFormat("{0:00} ", _data[j, i]);
                    }
                    sb.AppendLine();
                }
                return sb.ToString();
            }

            #endregion

            #region Properties

            private readonly int _rows;
            private readonly int _cols;
            private int[][] _indices;
            private int[,] _data;

            #endregion

        }

        /// <summary>
        ///  Program entry point
        /// </summary>
        static void Main()
        {
            var p = new Perm15X5();
            var count = 0;
            do
            {
                ++count;
                //Console.WriteLine("Instance {0}", count);
                //Console.Write(p.ToString());
            } while(p.GetNext());
            Console.WriteLine("count = {0}", count);
        }
    }
}


[解决办法]
15x5太大了点,用一个简化的例子(3x3)来说明,应该就比较清楚了
初始的时候行列如下:
1 4 7 
2 5 8
3 6 9
题目要求是变了以后任意两个不能有相同行,所以我们可以固定第一列(始终为1 2 3)因为我们会对其余的列进行遍历,所以这第一列就不换了,否则必然会导致重复。然后对后面几列进行这样(轮移)的变幻操作,以4 5 6为例:4 5 6 ---移动1格--> 6 4 5 ---移动2格--> 5 6 4,然后让这其中每一个相互组合,
比如让第二列移1格,第三列移2格就产(程序中GetNext()主要就在做这样的遍历操作——先让低列移,玩了“进位”到高位):
1 6 8
2 4 9
3 5 7
于是对这里3x3,有2列就一共包括初始的有9个组合(对于一般的M行xN列情形就是M^(N-1)个组合)。可以证明这样产生的不会有行重复,然后要证明这样产生的覆盖所有情况:由于对于M行xN列的数组之间没有行重复,数组内显然也没有行重复,由于所总共产生M^(N-1)个数组,所以总共包含了M^N个不同的行,而这正覆盖了在题目设定的列限制条件下所有可能的行情形(行中每个单元任取N个可选元素中的一个的全部组合)。所以充分性也就满足了。这里对于15x5应该产生50625个数组。

热点排行