C#行列式计算程序

原文链接:http://www.cnblogs.com/zhy2002/archive/2010/02/20/1669663.html PermutationGen用来枚举{1,...,n}的所有全排列。 D类用来计算行列式,只能对数值进行计算。 C#行列式计算程序C#行列式计算程序代码 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Determinant
{
    class Program
    {
        static void Main(string[] args)
        {
            //Console.WriteLine(D.SwitchCount(new int[] { 3, 2, 5, 1, 4 }));

            //D.PermutationGen pg = new D.PermutationGen(4);
            //pg.FastIteration = true;
            //foreach (var p in pg)
            //{
            //    Console.WriteLine(pg.PermutationToString(p));
            //}

            D d1 = new D(3);
            d1.Data[0, 0] = 1;
            d1.Data[0, 1] = 2;
            d1.Data[0, 2] = -4;
            d1.Data[1, 0] = -2;
            d1.Data[1, 1] = 2;
            d1.Data[1, 2] = 1;
            d1.Data[2, 0] = -3;
            d1.Data[2, 1] = 4;
            d1.Data[2, 2] = -2;
            Console.WriteLine(d1.Value);

            D d2 = new D(2);
            d2.Data[0, 0] = 3;
            d2.Data[0, 1] = 12;
            d2.Data[1, 0] = 2;
            d2.Data[1, 1] = 1;
            Console.WriteLine(d2.Value);
            Console.ReadKey();
        }
    }

    public class D
    {
        /// <summary>
        /// 计算1-n的一个全排列的逆序数
        /// </summary>
        /// <param name="permutation">a permutation of 1-permutation.Length</param>
        /// <returns></returns>
        public static int SwitchCount(int[] permutation)
        {
            int count = 0;
            if (permutation == null || permutation.Length == 0) throw new ArgumentException("输入不能为空", "permutation");
            if (permutation.Length == 1)
            {
                return 0;
            }
            for (int i = 0; i < permutation.Length; i++)
            {
                if (permutation[i] < 1 || permutation[i] > permutation.Length) throw new ArgumentException("只计算1-n的排列的逆序数");
            }
            for (int i = 0; i < permutation.Length; i++)
            {
                for (int j = i + 1; j < permutation.Length; j++)
                {
                    if (permutation[i] > permutation[j]) count++;
                    else if (permutation[i] == permutation[j]) throw new ArgumentException(String.Format("数字{0}重复出现在位置{1}和{2}", permutation[i], i, j), "permutation");
                }
            }
            return count;
        }

        double[,] data;
        int n;
        PermutationGen pg;

        public D(int rank)
        {
            if (rank < 2) throw new ArgumentException("Rank is at least 2.");
            n = rank;
            data = new double[rank, rank];
            data.Initialize();
        }

        public double[,] Data
        {
            get
            {
                return data;
            }
        }

        public double Value //calculate the value form the data given
        {
            get
            {
                double v = 0;
                if (pg == null)
                {
                    pg = new PermutationGen(n);
                }

                foreach (var p in pg)
                {
                    double u = 1;
                    for (int i = 0; i < n; i++)
                    { //固定行,选列
                        u *= data[i, p[i] - 1];
                    }
                    u *= ((SwitchCount(p) & 1) == 1 ? -1 : 1);
                    v += u;
                }

                return v;
            }
        }

        public class PermutationGen : IEnumerable<int[]>
        {
            int[] p, t, f;
            int len;
            StringBuilder pString;

            public bool ReturnNewPermutation
            {
                get;
                set;
            }

            public bool FastIteration
            {
                get;
                set;
            }

            public PermutationGen(int length)
            {
                len = length;
                p = new int[length];
                t = new int[length];//尚未被使用的数字
                f = new int[length + 1];
                for (int i = len; i >= 0; i--) //最前面两个元素不用
                {
                    f[i] = Factorial(i);
                }
            }

            public int Count
            {
                get
                {
                    return f[len];
                }
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="id">1至len</param>
            /// <returns></returns>
            public int[] GetPermutation(int id)
            {
                if (id >= f[len] || id < 0) throw new ArgumentException("1<=id<=len!");
                for (int i = 0; i < len; i++) //所有数字都未被使用
                {
                    t[i] = i + 1;
                }

                int r, n, m = id;
                for (int i = 0; i < len; i++)
                {
                    n = Math.DivRem(m, f[len - i - 1], out r);
                    p[i] = GetUnusedNumberN(n + 1);
                    m = r;
                }
                return p;
            }

            public string PermutationToString(int[] p)
            {
                int len = p.Length;
                if (pString == null)
                {
                    pString = new StringBuilder(len * 3);
                }
                pString.Length = 0;
                pString.Append(p[0]);
                for (int i = 1; i < len; i++)
                {
                    pString.Append(",");
                    pString.Append(p[i]);
                }

                return pString.ToString();
            }
            public string GetPermutationString()
            {
                return PermutationToString(p);
            }

            public static int Factorial(int n)
            {
                int result = 1;
                for (int i = n; i > 1; i--)
                {
                    result *= i;
                }
                return result;
            }

            /// <summary>
            /// 返回第n个未被使用的元素
            /// </summary>
            /// <param name="n"></param>
            /// <returns></returns>
            int GetUnusedNumberN(int n)
            {
                int count = 0;
                for (int i = 0; i < len; i++)
                {
                    if (t[i] != 0)
                    {
                        count++;
                        if (count == n)
                        {
                            int q = t[i];
                            t[i] = 0;//返回即被使用
                            return q;
                        }
                    }
                }

                return 0;//没有足够的剩余元素
            }

            /// <summary>
            /// return the smallest positive integer that is not included in the n elements of array starting for start
            /// </summary>
            int GetNextSmallest(int[] array, int start, int n, int searchStart)
            {
                int i;
                for (i = searchStart; i <= searchStart + n; i++)
                {
                    int j;
                    for (j = start; j < n; j++)
                    {
                        if (array[j] == i) break;
                    }
                    if (j == n)
                    {
                        return i;
                    }
                }
                return 0; //impossible, but required by grammar
            }

            #region IEnumerable<int[]> 成员

            public IEnumerator<int[]> GetEnumerator()
            {
                if (FastIteration)
                {
                    for (int i = 0; i < len; i++)
                    {
                        p[i] = i + 1;
                    }

                    for (int i = 0; i < f[len] - 1; i++)//返回第0号到倒数第二个排列
                    {
                        yield return ReturnNewPermutation ? p.Clone() as int[] : p;
                        //每次迭代构造下次应当返回的排列
                        for (int j = len - 1; j > 0; j--)
                        {
                            if (i / f[j] != (i + 1) / f[j])
                            {
                                //set p at level j
                                int k = len - j - 1;//convert to p index
                                p[k] = GetNextSmallest(p, 0, k, p[k] + 1);
                                k++;
                                while (k < len)
                                {
                                    p[k] = GetNextSmallest(p, 0, k, 1);
                                    k++;
                                }
                                break;
                            }
                        }
                    }
                    yield return ReturnNewPermutation ? p.Clone() as int[] : p;
                }
                else
                {
                    if (ReturnNewPermutation)
                    {
                        for (int i = 0; i < f[len]; i++)
                        {
                            yield return GetPermutation(i).Clone() as int[];
                        }
                    }
                    else
                    {
                        for (int i = 0; i < f[len]; i++)
                        {
                            yield return GetPermutation(i);
                        }
                    }
                }
            }

            #endregion

            #region IEnumerable 成员

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }

            #endregion
        }
    }
}

 

转载于:https://www.cnblogs.com/zhy2002/archive/2010/02/20/1669663.html

上一篇:[树状数组][权值线段树] Codeforces 1093E Intersection of Permutations


下一篇:567. Permutation in String