老赵的自然数分解——少侠之对象解

简介:

自然数分解算法的起因介绍,老赵

前几天贴了个非递归的 今天继续搞一个使用对象的解

 

坚持用对象来解决问题的一个原因,是想证明使用面向对象不是造成算法速度慢的根本原因

 例如,我这个面向对象的解,其运行速度似乎很牛的说,至少比我自己的非递归解要快10%。

核心类Item,代表算式中的每个项

派生类Tail,是最末尾的一项

主控类Splitter,负责构造以及输出

嫌文章太长的直接看源代码

 另外,Cat Chen的代码要简洁得多了,值得学习。 并且对于本问题的分析也比我说得要更清晰。

delegate void OverflowEventHandler();
delegate void AddedEventHandler(Item item);

    class Item
    {
        //回溯起点对象
        public static Item StartItem { get; set; }

        //总项数,最大值,最小值
        public static int N { get; set; }
        public static int Max { get; set; }
        public static int Min { get; set; }
        public static int Count { get; set; }

        //事件
        public event OverflowEventHandler Overflow;
        public event AddedEventHandler Added;

        //
        private int _index, _remainN;
        private int _subSum;
        protected int _value;

        //仅为了给尾部对象读取
        public int SubSum { get { return _subSum; } }

        public Item() { }

        public Item(int index,ref int sum)
        {
            _index=index;
            _remainN = (N - index-1 );
            if (sum <= _remainN * Max)
            {
                _value = Min;
            }
            else
            {
                _value = sum - _remainN * Max;
            }

            //检查并设置回溯位置
            CheckState(sum);

            sum -= _value;
            _subSum = sum;    
        }

        public void Add()
        {
            
            if (_value < (_subSum + _value) / (_remainN + 1))
            {//如果没有达到当前位置的最大允许值,递增自身
                _value++;
                _subSum--;
                CheckState(_subSum);
                //引发增加事件
                Count++;
                if (Added != null)
                    Added(this);
            }
            else
            {//如果达到当前位置的最大允许值,引发溢出事件
                if (Overflow != null)
                {
                    Overflow();
                }
            }
        }

        public virtual void Reset(Item item)
        {
            //计算新的当前值
            _value = item._subSum < _remainN * Max ? Min : item._subSum - _remainN * Max;
            _value = Math.Max(_value, item._value);
            _subSum = item._subSum-_value;
            CheckState(_subSum);
            Count++;
            if (Added != null)
                Added(this);
        }

        public override string ToString()
        {
            return _value.ToString();
        }

        private void CheckState(int sum)
        {
            //如果当前值小于允许最大值,则当前位置是回溯位置
            if (_value < (sum + _value) / (_remainN + 1))
                StartItem = this;
        }
    }

 

class Tail:Item
    {
        public new event AddedEventHandler Added;

        public Tail(int sum)
        {
            _value = sum;
        }

        public override void Reset(Item item)
        {
            _value = item.SubSum;
            if (Added != null)
                Added(this);
        }
    }

 

class Splitter
    {
        //项目数足
        Item[] _items;
        StringBuilder _builder;

        //记录当前结果,并引发下一次计算
        void Splitter_Added(Item item)
        {
            _builder.AppendLine(string.Join("+",Array.ConvertAll(_items,i=>i.ToString())));
            Item.StartItem.Add();
        }

        //第一个个项产生溢出,设置起点为空,终止计算
        void Splitter_Overflow()
        {
            Item.StartItem = null;
        }

        public string PrintDivision(int sum, int n, int min, int max)
        {
            string returnValue = "";
 
            Item.N = n;
            Item.Max = max;
            Item.Min = min;
            _builder = new StringBuilder();
            _items = new Item[n];

            int i;
            //构造项目数组
            for (i = 0; i < n-1; i++)
            {
                _items[i] = new Item(i,ref sum);
                if (i > 0)
                {
                    //关联前后项目的事件
                    _items[i - 1].Added += _items[i].Reset;
                    _items[i].Overflow += _items[i - 1].Add;
                }
            }
            //增加尾项目对象及其事件关联
            _items[i] = new Tail(sum);
            _items[i - 1].Added += _items[i].Reset;
            //第一项溢出事件关联
            _items[0].Overflow += new OverflowEventHandler(Splitter_Overflow);
            //最后一项置位完成事件关联
            _items[n - 1].Added += new AddedEventHandler(Splitter_Added);
            
            //在存在未溢出位置时一直循环
            while(Item.StartItem!=null)
                //这里实参是不需要的,不想继续优化了,呵呵
                    Splitter_Added(_items[n - 1]);
            //记录最后一次的结果
            returnValue = _builder.ToString();
            Console.WriteLine(Item.Count);
            return returnValue;
        }
    }

 

class Program
    {
        static void Main(string[] args)
        {
            TimeSpan ts;
            System.IO.StreamWriter w ;
            string st;
            DateTime dt;

            w = new System.IO.StreamWriter("output.txt");
            Splitter s = new Splitter();
            dt = DateTime.Now;
            st = s.PrintDivision(80, 25, 1, 30);
            ts = DateTime.Now - dt;
            Console.WriteLine( ts.TotalMilliseconds);
            w.Write(st);
            w.Close();
        }
    }

 

谢谢大家观赏

 

 源代码

作者: 徐少侠
出处: http://www.cnblogs.com/Chinese-xu/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
如有问题,可以通过 Chinese_Xu@126.com 联系我,非常感谢。

分享家:Addthis中文版
分类: C#, .Net

本文转自徐少侠博客园博客,原文链接:http://www.cnblogs.com/Chinese-xu/archive/2009/06/29/1513398.html,如需转载请自行联系原作者
目录
相关文章
|
2月前
【代数学作业5】理想的分解:高斯整数环中理想的结构,并根据其范数和素数的性质进行分解
【代数学作业5】理想的分解:高斯整数环中理想的结构,并根据其范数和素数的性质进行分解
32 0
|
4月前
构造命题公式的真值表
构造命题公式的真值表
67 0
|
6月前
|
算法 测试技术 C#
C++前缀和算法:构造乘积矩阵
C++前缀和算法:构造乘积矩阵
|
8月前
|
C++
数的分解
把 2019分解成 3个各不相同的正整数之和,并且要求每个正整数都不包含数字2和4,一共有多少种不同的分解方法?
38 0
|
9月前
1200:分解因数
1200:分解因数
|
Python
Python 分解质因数(编写函数实现:输入一个正整数n,把数字n分解成不能再分解因子的乘法,比如:8=2*2*2, 10 = 2*5,而不是 8 = 2 * 4 这种可以再分解的。)
Python 分解质因数(编写函数实现:输入一个正整数n,把数字n分解成不能再分解因子的乘法,比如:8=2*2*2, 10 = 2*5,而不是 8 = 2 * 4 这种可以再分解的。)
726 0
|
机器学习/深度学习 vr&ar
矩阵的等价,相似,合同,正定判定和关系
如果矩阵可逆,那么它的逆矩阵和它的伴随矩阵之间只差一个系数。然而,伴随矩阵对不可逆的矩阵也有定义,并且不需要用到除法。
1015 0
矩阵的等价,相似,合同,正定判定和关系
|
算法
[算法]将一个正整数拆分成若干个正整数的和,输出所有的结果不重复
推荐先看我的一篇介绍Set去重的博文地址是 http://blog.csdn.net/bug_moving 看了这个之后,再来看下面的程序基本就能看懂了 题目 我也不太记得,因为是朋友给我口述的,然后给了我一个截图,看了图片大致也能知道题目要我们做什么 package yn; import java.util.ArrayList; import java.
2749 0
|
机器学习/深度学习 移动开发
【计算理论】可判定性 ( 对角线方法 | 证明自然数集 N 与实数集 R 不存在一一对应关系 )
【计算理论】可判定性 ( 对角线方法 | 证明自然数集 N 与实数集 R 不存在一一对应关系 )
284 0
【组合数学】生成函数 ( 使用生成函数求解不定方程解个数示例 2 | 扩展到整数解 )
【组合数学】生成函数 ( 使用生成函数求解不定方程解个数示例 2 | 扩展到整数解 )
154 0