2021-08-29 代码

using System;
using System.Text.RegularExpressions;

namespace CodeS
{
    class Program_1
    {
        static string test_data = "0 1 0 0 0 1 4 0 0 3 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0";
        static int line = 0;
        static int [] data;
        static stNode [] stTree;
        static int nodeCount = 0;
        static int treeMakeIndex = 0;
        static bool [] stables;
        static sRate [] rateRet; 

        public struct sRate
        {
            public int fenzi;
            public int fenmu;
        }

        public struct stNode
        {
            public int stateId;
            public bool bRepeat;
            public int [] child;
            public int childCount;
            public int parent;
            public sRate rate;
            
        }

        // 生成树
        static void MakeTree()
        {
            stTree = new stNode[nodeCount];
            MakeNode(0, -1);

            int [] tdata = new int[data.Length];
            for(int i = 0; i < data.Length; i++)
                tdata[i] = data[i];
            for(int i = 0; i < data.Length; i++)
            {
                if (tdata[i] != 0)
                {
                    MakeNode(i%line, i/line);
                }
            }
        }   

        // 生成树节点
        static void MakeNode(int childId, int parentId)
        {
            stNode tempNode = new stNode();
            tempNode.stateId = childId;
            tempNode.parent = parentId;
            
            int index = 0;
            bool bExist = FindNode(childId, ref index);
            tempNode.bRepeat = bExist;
            
            int sum = 0;
            if (parentId >= 0)
            {
                for(int i = 0; i < line; i ++)
                    if(data[parentId*line+i] != 0)
                    {
                        sum += data[parentId*line+i];
                    }
                tempNode.rate.fenzi = data[parentId*line+childId];
                tempNode.rate.fenmu = sum;
            }

            if (!bExist)    // 重复节点,不再添加子节点数据
            {
                int count = 0;
                for(int i = 0; i < line; i ++)
                    if(data[childId*line+i] != 0)
                    {
                        count ++;
                    }
                tempNode.childCount = count;
                tempNode.child = new int[count];
                int j = 0;
                for(int i = 0; i < line; i ++)
                    if(data[childId*line+i] != 0)
                    {
                        tempNode.child[j++] = i;

                    }
            }

            stTree[treeMakeIndex ++] = tempNode;
        }

        // 查找树节点
        static bool FindNode(int id, ref int index, bool repeatNode = true)
        {
            for(int i = 0; i < treeMakeIndex; i ++)
            {
                if (stTree[i].stateId == id)
                {
                    if((!repeatNode && !stTree[i].bRepeat) || repeatNode)
                    {
                        index = i;
                        return true;
                    }
                }
            }
            return false;
        }

        // 判定是否重复节点
        static bool RepeatNode(int id)
        {
            for(int i = 0; i < treeMakeIndex; i ++)
            {
                if (stTree[i].stateId == id && stTree[i].bRepeat)
                {
                    return true;
                }
            }
            return false;
        }

        // 逻辑计算主入口
        static void DoCal()
        {
            // 稳定态
            stables = new bool[line];
            rateRet = new sRate[line];
            for(int i = 0; i < line; i ++)
            {
                int sum = 0;
                for(int j = 0; j < line; j ++)
                {
                    sum += data[i*line + j];
                }
                if (sum == 0)
                    stables[i] = true;
                else
                    stables[i] = false;
            }

            for (int i = 0; i < line; i ++)
            {
                if (stables[i])
                {
                    int index = 0;
                    bool bExist = FindNode(i, ref index, false);
                    if (bExist)
                    {
                        // 自身节点
                        CalRate(index, ref rateRet[i].fenzi, ref rateRet[i].fenmu);
                        // 自身重复节点
                        for(int j = 0; j < stTree.Length; j ++)
                        {
                            int fenzi = 0;
                            int fenmu = 0;
                            if (stTree[j].stateId == i && stTree[j].bRepeat)
                            {
                                CalRate(index, ref fenzi, ref fenmu);
                                DoAdd(ref rateRet[i].fenzi, ref rateRet[i].fenmu, fenzi, fenmu);
                            }
                        }
                        // 父节点是重复节点
                        int parentId = stTree[index].parent;
                        while(true)
                        {
                            if (parentId == -1)
                                break;

                            if (RepeatNode(parentId))
                            {
                                int pindex = 0;
                                if(FindNode(parentId, ref pindex, false))
                                {
                                    int fenzi1 = 0;
                                    int fenmu1 = 0;
                                    CalRate(index, ref fenzi1, ref fenmu1, pindex);

                                    int _fenzi = 0;
                                    int _fenmu = 0;
                                    for (int k = 0; k < treeMakeIndex; k ++)
                                    {
                                        int _fenzi1 = fenzi1;
                                        int _fenmu1 = fenmu1;
                                        if (stTree[k].stateId == parentId && stTree[k].bRepeat)
                                        {
                                            int fenzi2 = 0;
                                            int fenmu2 = 0;
                                            CalRate(k, ref fenzi2, ref fenmu2);
                                            DoMulti(ref _fenzi1, ref _fenmu1, fenzi2, fenmu2);
                                            DoMulti(ref _fenzi1, ref _fenmu1, fenmu2, fenmu2-fenzi2);
                                            DoAdd(ref _fenzi, ref _fenmu, _fenzi1, _fenmu1);
                                        }
                                    }
                                    DoAdd(ref rateRet[i].fenzi, ref rateRet[i].fenmu, _fenzi, _fenmu);
                                }
                            }

                            int _t = 0;
                            if (FindNode(parentId, ref _t, false))
                                parentId = stTree[_t].parent;
                            else
                                break;
                        }
                        
                        //Console.Write(rateRet[i].fenzi); Console.Write('/'); Console.Write(rateRet[i].fenmu); Console.WriteLine();
                    }
                }
            }
        }

        static void CalRate(int index, ref int fenzi, ref int fenmu, int toIndex = 0)
        {
            if (fenzi == 0) fenzi = 1;
            if (fenmu == 0) fenmu = 1;

            if (index > 0 && index != toIndex)
            {
                fenzi *= stTree[index].rate.fenzi;
                fenmu *= stTree[index].rate.fenmu;
                int pindex = 0;
                if (FindNode(stTree[index].parent, ref pindex, false))
                {
                    CalRate(pindex, ref fenzi, ref fenmu, toIndex);
                    SimpleFenShu(ref fenzi, ref fenmu);
                }
            }
        }

        // 分数简化
        static void SimpleFenShu(ref int fenzi, ref int fenmu)
        {
            int temp = Math.Min(fenzi, fenmu);
            if (temp > 1)
            {
                for(int i = 2; i <= temp; )
                {
                    if(temp > 1 && fenzi % i == 0 && fenmu % i == 0)
                    {
                        fenzi = fenzi / i;
                        fenmu = fenmu / i;
                        i = 2;
                        temp = Math.Min(fenzi, fenmu);
                    }
                    else
                        i ++;
                }
            }
        }

        // 求最小公倍数
        static int MinGongBeiShu(int [] input)
        {
            int max = 0;
            int maxGBS = 1;
            for(int i = 0; i < input.Length; i ++)
            {
                if (input[i] > 0)
                {
                    maxGBS *= input[i];
                    if (max < input[i])
                        max = input[i];
                }
                    
            }
            int nRet = 0;
            if (max > 0)
            {
                int max_i = maxGBS / max;
                for (int i = 1; i <= max_i; i ++)
                {
                    bool bNoRemain = true;
                    for(int j = 0; j < input.Length; j ++)
                    {
                        if (input[j] > 0 && (i*max)%input[j] != 0)
                        {
                            bNoRemain = false;
                            break;
                        }
                    }
                    if (bNoRemain)
                    {
                        nRet = i*max;
                        break;
                    }
                }
            }
            return nRet;
        }

        // 分数加法
        static void DoAdd(ref int fenzi1, ref int fenmu1, int fenzi2, int fenmu2)
        {
            if (fenzi1 == 0 || fenzi2 == 0)
            {
                fenzi1 = fenzi1 + fenzi2;
                fenmu1 = fenmu1 + fenmu2;
            }
            else
            {
                fenzi1 = fenzi1 * fenmu2 + fenzi2 * fenmu1;
                fenmu1 = fenmu1 * fenmu2;
            }
            SimpleFenShu(ref fenzi1, ref fenmu1);
        }

        // 分数乘法
        static void DoMulti(ref int fenzi1, ref int fenmu1, int fenzi2, int fenmu2)
        {
            fenzi1 = fenzi1 * fenzi2;
            fenmu1 = fenmu1 * fenmu2;
            SimpleFenShu(ref fenzi1, ref fenmu1);
        }

        static void Main(string[] args)
        {
            // 数据
            string [] _s = test_data.Split(' ');
            data = new int[_s.Length];
            nodeCount = 1;
            for(int i = 0; i < _s.Length; i ++)
            {
                data[i] = int.Parse(_s[i]);
                if (data[i] != 0)
                    nodeCount ++;
                //Console.Write(data[i]); Console.Write(' ');
            }
            line = (int)Math.Sqrt(_s.Length);
            
            // 生成树
            MakeTree();

            // 算法入口
            DoCal();

            // 数据规整
            int [] outdata = new int[line];
            for (int i = 0; i < line; i ++)
            {
                if (stables[i])
                {
                    int index = 0;
                    if (FindNode(i, ref index))
                    {
                        outdata[i] = rateRet[i].fenmu;
                    }
                }
            }
            int gbs = MinGongBeiShu(outdata);
            
            // 输出
            for (int i = 0; i < line; i ++)
            {
                if (stables[i])
                {
                    if (outdata[i] > 0)
                        Console.Write(gbs/rateRet[i].fenmu*rateRet[i].fenzi);
                    else
                        Console.Write(0);
                    Console.Write(' ');
                }
            }
            Console.Write(gbs);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值