Free Hit Counters
http://www.dellasdeals.com

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

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

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

 

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

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

 

谢谢大家观赏

 

 源代码

posted @ 2009-06-29 17:21  徐少侠  阅读(2865)  评论(6编辑  收藏  举报
作者:徐少侠 出处:http://www.cnblogs.com/Chinese-xu/

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