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

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

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

例如,我这个面向对象的解,其运行速度似乎很牛的说,至少比我自己的非递归解要快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();
        }
    }

谢谢大家观赏

源代码

老赵的自然数分解——少侠之对象解相关推荐

  1. 【转载】Erlang精彩讨论-回“老赵”关于“Erlang中最大的问题”

    原文:http://erlang-china.org/study/puzzle-in-erlang_pattern_match.html/comment-page-1#comments http:// ...

  2. 老赵谈IL(3):IL可以看到的东西,其实大都也可以用C#来发现

    在上一篇文章中,我们通过一些示例谈论了IL与CLR中的一些特性.IL与C#等高级语言的作用类似,主要用于表示程序的逻辑.由于它同样了解太多CLR中的高级特性,因此它在大部分情况下依旧无法展现出比那些高 ...

  3. 艾伟:老赵谈IL(3):IL可以看到的东西,其实大都也可以用C#来发现

    在上一篇文章中,我们通过一些示例谈论了IL与CLR中的一些特性.IL与C#等高级语言的作用类似,主要用于表示程序的逻辑.由于它同样了解太多CLR中的高级特性,因此它在大部分情况下依旧无法展现出比那些高 ...

  4. 把老赵的页面缓存片断改一下,呵呵

    老赵同志写的页面缓存片断不错,用着方便,但我感觉在前端调用上有些不便,可以我把他的代码又改了一下,呵呵! 老赵代码的调用: Before Rendering: <%= DateTime.Now ...

  5. VS 2008的JavaScript代码提示功能 (学习老赵视频的笔记)

    学习老赵的视频ASP.NET AJAX深入浅出系列课程(19):VS 2008的JavaScript代码提示功能(Level 200) 自己做的demo,记下来以便查阅!感谢赵老师! 原来js还可以像 ...

  6. 《老赵手动整理的Python笔记(一)》

    <老赵手动整理的Python笔记(一)> 下面的内容的都是老赵在学习Python过程中记录的一些知识点,还有对于不理解的地方的一些研究.老赵有点强迫症,对于不明白的事情总想去弄明白,不然饭 ...

  7. 根据老赵轻量级Actor进行修改的Actor模型

    学习了老赵轻量级Actor模型,并在实际中使用,效果不错. 老赵轻量级Actor模型: ActorLite:一个轻量级Actor模型实现(上) ActorLite:一个轻量级Actor模型实现(中) ...

  8. 解读网络“攻城狮”的发展---老赵带你铺一段路

    成为网络工程师要学什么.如何学.在哪儿学,网络工程师的发展如何.薪资待遇如何等问题困扰着很多网络技术人员,尤其是正在学校苦苦寻求真理的同学们.我也是一名在校大学生,深知现在同学们的苦恼.如果能掌握关于 ...

  9. 用dotTace模仿下老赵的“使用Profiler分析程序性能”

    最近看到老赵博客"使用Profiler分析程序性能"(http://www.cnblogs.com/JeffreyZhao/archive/2009/12/22/profiler- ...

最新文章

  1. 十、图像参数集Picture Paramater Set(PPS)解析
  2. 在北京,一款App从无到有至少需要100万?
  3. VS 中配置使用Visual SVN系列 三:TortoiseSVN Client(客户端)下载和安装
  4. input两种默认显示文字方式
  5. 数据挖掘-贝叶斯定理
  6. ubuntu下无法在根目录创建文件夹;permission denied 权限不足问题解决方法
  7. 【Fedora20】 samba配置
  8. Mr.J-- HTTP学习笔记(四)-- 连接管理
  9. Windows 平台下基于MinGW和Qt 的OpenCV 之CMake 项目配置
  10. javascript this
  11. Docker 之MySQL 重启,提示Error response from daemon: driver failed programming external connectivity on **
  12. 【ExtJS6开发日记(一)】——Chart类型无法加载,及ExtJS中出现requires无法加载情况的统一说明
  13. NR: PointA,offsetToPonitA,kSSB三者关系。
  14. GD32F4(3): 在keil软件中使用GD-LINK下载调试
  15. 给高科技强国的后来者埋下的痛
  16. 【论文翻译】Cluster Contrast for Unsupervised Person Re-Identification(2021)
  17. 大数乘法(快速傅立叶变换)下
  18. 网络基础之计算机网络参考模型(OSI参考模型与TCP/IP协议簇)
  19. 三井住友銀行相关资料
  20. [Cortex-M3]-0-M3介绍

热门文章

  1. java for循环迭代_JAVA中的for-each循环与迭代
  2. python输出质数序列_用python打印素数序列
  3. 串口 能 按位传输吗_六类网线能传输多少米?家装六类网线有必要吗?
  4. .NET Core 6.0之读取配置文件
  5. win8计算机安全模式,安全模式,教您Win8怎么进入安全模式
  6. django外调用url_Django学习(url配置及参数获取)
  7. 关于ValueError: Unknown projection ‘3d‘报错的解决方法
  8. python计算机_基础python计算机知识
  9. 计算机应用开设学校 四川,成都计算机类专业开设的院校有哪些
  10. 南华大学c语言多少分才能过_成人高考难吗?多少分可以过?