代码改变世界

算法——动态规划

2012-12-26 19:33  msfte  阅读(181)  评论(0编辑  收藏  举报

1,编程之美1.4买书问题

上柜的《哈利波特》平装本系列,一共有五卷。假设每一卷单独销售均需8欧元。如果读者一次购买不同的两卷,就可以扣除5%的费用,三卷则更多。假设具体折扣的情况如下:

        本数    2       折扣   5%

        本数    3       折扣  10%

        本数    4       折扣  20%

        本数    5       折扣  25% 

问题:设计出算法,能够计算出读者所购买的一批书的最低价格。

备忘录算法:

class BuyBook
    {
        public void Run()
        {
            var result = DynamicProgramming(new int[] { 2,2,2,1,1});
        }

        double DynamicProgramming(int[] books)
        {
            books = books.OrderByDescending(c => c).ToArray();
            return DynamicProgrammingRecur(books);
        }

        double DynamicProgrammingRecur(int[] books)
        {
            if (books[0] == 0)
                return 0;
            if (cache.ContainsKey(new BookState(books)))
                return cache[new BookState(books)];
            books = books.OrderByDescending(c => c).ToArray();
            double situation1 = 8 + DynamicProgrammingRecur(new int[] { books[0] - 1, books[1], books[2], books[3], books[4] });
            double situation2 = books[1] != 0 ? 8 * 2 * (1 - 0.05) + DynamicProgrammingRecur(new int[] { books[0] - 1, books[1] - 1, books[2], books[3], books[4] }) : 0;
            double situation3 = books[2] != 0 ? 8 * 3 * (1 - 0.1) + DynamicProgrammingRecur(new int[] { books[0] - 1, books[1] - 1, books[2] - 1, books[3], books[4] }) : 0;
            double situation4 = books[3] != 0 ? 8 * 4 * (1 - 0.2) + DynamicProgrammingRecur(new int[] { books[0] - 1, books[1] - 1, books[2] - 1, books[3] - 1, books[4] }) : 0;
            double situation5 = books[4] != 0 ? 8 * 5 * (1 - 0.25) + DynamicProgrammingRecur(new int[] { books[0] - 1, books[1] - 1, books[2] - 1, books[3] - 1, books[4] - 1 }) : 0;
            double max = GetMax(new double[] { situation1, situation2, situation3, situation4, situation5 });
            cache.Add(new BookState(books), max);
            return max;
        }

        double GetMax(double[] items)
        {            
            double max = items[0];
            for (int i = 1; i < items.Length; i++)
                if (items[i] > max)
                    max = items[i];
            return max;
        }

        Dictionary<BookState, double> cache = new Dictionary<BookState, double>();


    }

    struct BookState
    {
        public BookState(int[] state)
        {
            this.State = state;
        }

        public int[] State;

        public override bool Equals(object obj)
        {
            int[] objState = obj as int[];
            if (objState == null)
                return false;
            else
            {
                for (int i = 0; i < State.Length; i++)                
                    if (State[i] != objState[i])
                        return false;                
                return true;
            }
        }

        public override int GetHashCode()
        {
            int hashCode = 0;
            for (int i = 0; i < State.Length; i++)
            {
                int currentNumber = State[i];
                for (int j = 0; j <= i; j++)
                    currentNumber *= 10;
                hashCode += currentNumber;
            }
            return hashCode;            
        }
    }