C#实现递归矩阵连乘(动态规划的递归自顶向下,非递归自地向上)

源文件:http://pan.baidu.com/share/link?shareid=481923&uk=3912660076

//Main:

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

namespace MatrixMultiplication
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("Please enter numbers of Matix:");
            int Mnum = Convert.ToInt32(Console.ReadLine());

            MatrixMultiplication obj = new MatrixMultiplication(Mnum + 1);

            int[,] MatrixThree = obj.NormalRecursionMatrixMultiplication(obj.MatrixChain);
            obj.ShowMatrix(MatrixThree);
            obj.BottomUpNotRecursionMatrixMultiplication(obj.MatrixChain);
            Console.WriteLine();
            obj.TopDownRecursionMatrixMultiplication(obj.MatrixChain);
            Console.ReadKey();

        }
    }
}

//Class

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

namespace MatrixMultiplication
{
    class MatrixMultiplication
    {
        // bool ErrorTorF;
        private int[,] MatrixOne;
        private int[,] MatrixTwo;
        private int[,] MatrixThree;
        private int index = 1;//
        private string[] An;//矩阵链字符格式化
        private string LParenthesis = "(";
        private string RParenthesis = ")";

        //数据仓库啊...哈哈
        private int[,] initMatrixCalcData;//0行0列除外 1行1列:完全加括号矩阵链1~1计算量...

        private int[,] MatrixChainValue;//0行除外 1行:第一个矩阵...  列:连续维数值

        private int[,] TracePoint;//row:始矩阵,col:末矩阵,最小矩阵链计算量的断开位置。            

        public int[,] MatrixChain
        {
            get { return MatrixChainValue; }
        }

        public MatrixMultiplication(int initMatrixChain)
        {
            //牺牲储存空间...
            MatrixChainValue = new int[initMatrixChain, 2];//n个矩阵n+1行 0行不在其中
            InitializeArray();
        }
        //储存各矩阵为几行几列矩阵
        private void InitializeArray()
        {
            An = new string[MatrixChainValue.GetLength(0)];
            //i表示第i个矩阵...
            for (int i = 1; i < MatrixChainValue.GetLength(0); i++)
            {
                An[i] = "" + i.ToString();
            Error://0,row  0,col ; 1,row  1,col ; ...
                Console.WriteLine("Please enter the size of the {0} Matrix(row and low):", i);
                int row = Convert.ToInt32(Console.ReadLine());
                MatrixChainValue[i, 0] = row;//行值
                int col = Convert.ToInt32(Console.ReadLine());
                MatrixChainValue[i, 1] = col;//列值
                if (i > 1 && MatrixChainValue[i, 0] != MatrixChainValue[i - 1, 1])
                {
                    Console.WriteLine("Error !");
                    goto Error;
                }
            }
            Console.WriteLine("Dispaly Matrix Chain:");
            Console.WriteLine();
            for (int i = 1; i < An.Length; i++)
            {
                Console.Write("{0,8}", An[i]);
            }
            Console.WriteLine();
            for (int i = 1; i < MatrixChainValue.GetLength(0); i++)
            {
                Console.Write("{0,4}{1,5}", MatrixChainValue[i, 0], " ");
                if (i == (MatrixChainValue.GetLength(0) - 1))
                    Console.Write("{0,4}", MatrixChainValue[i, 1]);
            }
            Console.WriteLine();
        }
        /// <summary>
        /// 普通矩阵相乘
        /// </summary>
        /// <param name="MatrixChain">保存矩阵的行和列数(去掉重复的)</param>
        /// <returns>最终矩阵</returns>
        public int[,] NormalRecursionMatrixMultiplication(int[,] MatrixChain)
        {
            if (index < MatrixChain.GetLength(0))
            {
                if (index == 1)
                {
                    MatrixOne = new int[MatrixChain[index, 0], MatrixChain[index++, 1]];
                    MatrixTwo = new int[MatrixChain[index, 0], MatrixChain[index++, 1]];
                }
                else
                {
                    MatrixOne = MatrixThree;
                    MatrixTwo = new int[MatrixChain[index, 0], MatrixChain[index++, 1]];
                }
                MatrixThree = new int[MatrixOne.GetLength(0), MatrixTwo.GetLength(1)];
                for (int i = 0; i < MatrixOne.GetLength(0); i++)//第一个矩阵的行
                {
                    for (int j = 0; j < MatrixTwo.GetLength(1); j++)//第二个矩阵的列
                    {
                        int temp = 0;
                        for (int k = 0; k < MatrixTwo.GetLength(0); k++)//第一个矩阵的列同增,第二个矩阵的行同增。一的列或二的行为index
                        {
                            temp += MatrixOne[i, k] * MatrixTwo[k, j];
                        }
                        MatrixThree[i, j] = temp;
                    }
                }
                NormalRecursionMatrixMultiplication(MatrixChain);
            }
            return MatrixThree;
        }
        
        /// <summary>
        /// 动态规划自底向上
        ///非递归这里不记录非最优的值...
        /// </summary>
        /// <param name="MatrixChain">保存矩阵的行和列数(去掉重复的)</param>
        public void BottomUpNotRecursionMatrixMultiplication(int[,] MatrixChain)
        {
            //储存链矩阵的计算量
            initMatrixCalcData = new int[MatrixChain.GetLength(0), MatrixChain.GetLength(0)];
            //储存断点
            TracePoint = new int[MatrixChain.GetLength(0), MatrixChain.GetLength(0)];
            //单个矩阵计算量为 0 ,看做完全加括号矩阵
            for (int i = 1; i < initMatrixCalcData.GetLength(0); i++)
                initMatrixCalcData[i, i] = 0;
            //本质在填充最优二维表initMatriCalcData...假设5个矩阵
            //i表示矩阵链跨度最长为整个矩阵链-1(这里是"<")i:max:4
            for (int i = 1; i < initMatrixCalcData.GetLength(0) - 1; i++)
            {
                //j表示起始矩阵,j+i表示终止矩阵=1+4=5
                for (int j = 1; j + i < initMatrixCalcData.GetLength(0); j++)//矩阵链
                {
                    //保存矩阵链不同分割位置的计算量
                    int tempinitMatrixCalcData = 0;
                    //k表示断点位置,从起始矩阵开始
                    for (int k = j; k < j + i; k++)
                    {
                        //在矩阵链中对每个合适的断点位置计算矩阵的计算量(左链+左*右+右链)
                        //初始tempinitMatrixCalcData一下
                        tempinitMatrixCalcData = initMatrixCalcData[j, k] + MatrixChainValue[j, 0] * MatrixChainValue[k, 1] * MatrixChainValue[j + i, 1] + initMatrixCalcData[k + 1, j + i];
                        if (k == j)
                        {
                            //假设最小计算量的分割位置是第一个
                            initMatrixCalcData[j, j + i] = tempinitMatrixCalcData;
                            TracePoint[j, j + i] = j;
                        }
                        //记录最小计算量的断点(矩阵链为2 时只有一种可能)
                        if (tempinitMatrixCalcData < initMatrixCalcData[j, j + i])
                        {
                            //存在其他最小分割点计算量
                            TracePoint[j, j + i] = k;
                            initMatrixCalcData[j, j + i] = tempinitMatrixCalcData;
                        }
                    }
                }
            }
            //最后输出计算量最小的矩阵链相乘次序。
            DynamicProgramming(1, MatrixChainValue.GetLength(0) - 1, TracePoint);
            Show();
        }

        /// <summary>
        /// 动态规划自顶向下
        /// </summary>
        /// <param name="MatrixChain">保存矩阵的行和列数(去掉重复的)</param>
        public void TopDownRecursionMatrixMultiplication(int[,] MatrixChain)
        {
            //储存链矩阵的计算量
            initMatrixCalcData = new int[MatrixChain.GetLength(0), MatrixChain.GetLength(0)];
            //单个矩阵计算量为 0 ,看做完全加括号矩阵
            //储存断点
            TracePoint = new int[MatrixChain.GetLength(0), MatrixChain.GetLength(0)];

            //for (int i = 1; i < initMatrixCalcData.GetLength(0); i++)
            //    initMatrixCalcData[i, i] = 0;

            Recursion(1, MatrixChainValue.GetLength(0) - 1, initMatrixCalcData, TracePoint);
            //最后输出计算量最小的矩阵链相乘次序。
            DynamicProgramming(1, MatrixChainValue.GetLength(0) - 1, TracePoint);
            Show();
        }//得到最小值              1                 6
        private int Recursion(int startMatrix, int endMatrix, int[,] initMatrixCalcData, int[,] TracePoint)
        {
            if (startMatrix == endMatrix)
                return 0;
            //i表示断点
            for (int i = startMatrix; i < endMatrix; i++)
            {
                //                                              1
               int tempMatrixCalcData = Recursion(startMatrix, i, initMatrixCalcData, TracePoint) +
                MatrixChainValue[startMatrix, 0] * MatrixChainValue[i/*2*/, 1] * MatrixChainValue[endMatrix, 1] +
                Recursion(i + 1, endMatrix, initMatrixCalcData, TracePoint);
                if (i == startMatrix)
                {
                    //假设最小计算量的分割位置是第一个
                    initMatrixCalcData[startMatrix, endMatrix] = tempMatrixCalcData;
                    TracePoint[startMatrix, endMatrix] = startMatrix;
                }
                //记录最小计算量的断点(矩阵链为2 时只有一种可能)
                if (tempMatrixCalcData < initMatrixCalcData[startMatrix, endMatrix])
                {
                    //存在其他最小分割点计算量
                    TracePoint[startMatrix, endMatrix] = i;
                    initMatrixCalcData[startMatrix, endMatrix] = tempMatrixCalcData;
                }
            }
            return initMatrixCalcData[startMatrix, endMatrix];
        }
        /// <summary>
        /// 对矩阵进行加括号
        /// </summary>
        /// <param name="startMatrix"></param>
        /// <param name="endMatrix"></param>
        /// <param name="TracePoint">记录的断点</param>
        private void DynamicProgramming(int startMatrix, int endMatrix, int[,] TracePoint)
        {
            if (startMatrix == endMatrix)
                return;
            //startMatrix表示起始矩阵,endMatrix表示终止矩阵.
            //先左后右
            DynamicProgramming(startMatrix, TracePoint[startMatrix, endMatrix], TracePoint);
            DynamicProgramming(TracePoint[startMatrix, endMatrix] + 1, endMatrix, TracePoint);
            //以矩阵链的分割从外向内输出(重新定义赋值)==括住子矩阵链
            //先右后左
            //后进(内)先出(外)...            
            An[startMatrix] = LParenthesis + An[startMatrix];
            //An[TracePoint[startMatrix, endMatrix]] += RParenthesis;
            //这内两个结合外两个是为自身加括号的
            //An[TracePoint[startMatrix, endMatrix] + 1] = LParenthesis + An[TracePoint[startMatrix, endMatrix] + 1];
            An[endMatrix] += RParenthesis;
        }
        private void Show()
        {
            Console.WriteLine("Result:");
            Console.WriteLine("Minimum Calculation is: {0}", initMatrixCalcData[1, MatrixChainValue.GetLength(0) - 1]);
            for (int i = 1; i < An.Length; i++)
            {
                Console.Write(An[i]);
            }
        }
        
        /// <summary>
        /// 输出相乘后的矩阵
        /// </summary>
        /// <param name="Matrix">最终得到的矩阵</param>
        public void ShowMatrix(int[,] Matrix)
        {
            for (int j = 0; j < Matrix.GetLength(0); j++)
            {
                for (int i = 0; i < MatrixThree.GetLength(1); i++)
                {
                    Console.Write(" {0}", Matrix[j, i]);
                }
                Console.WriteLine();
            }
        }

    }
}

//运行结果

  由于重复用运一个An,第二个会出项多余的括号.......出现0没有实现数据的输入...


原文地址:https://www.cnblogs.com/wjshan0808/p/3102680.html