遞推,遞迴,貪心,列舉思想

綠龍術士發表於2018-04-12

轉載自:http://www.cnblogs.com/huangxincheng/category/340148.html

· 演算法 (真正的程式設計應該是:程式設計=XX語言+資料結構+演算法)

· 遞推思想

· 概念通過已知條件,利用特定關係逐步遞推,最終得到結果為止,核心就是不斷的利用現有資訊推匯出新的東西。

· 分類:“順推”,“逆推”

· “順推”是指通過條件推出結果

· “逆推”是指通過結果推出條件

· 例子:“斐波那契”數列,銀行取錢

 

        #region 遞推思想

        /// <summary>
        /// 斐波那契數列
        /// </summary>
        public static void Fibonacci()
        {
            int month = 12;
            int[] fab = new int[month];
            fab[0] = 1;
            fab[1] = 1;
            for (int i = 2; i < month; i++)
            {
                fab[i] = fab[i - 1] + fab[i - 2];
            }
            for (int i = 0; i < fab.Length; i++)
            {
                Console.WriteLine($"第{i + 1}個月的小兔子為:{fab[i]}");
            }
        }

        /// <summary>
        /// 一個富二代給他兒子的四年大學生活存一筆錢,富三代每月只能取3k作為下個月的生活費,採用的是整存零取的方式,
        /// 年利率在1.71%,請問富二代需要一次性存入多少錢。
        /// 思路: 這個題目是我們知道了結果,需要逆推條件, 第48月富三代要連本帶息的把3k一把取走,那麼
        /// 第47月存款應為: (第48個月的存款+3000)/(1+0.0171/12(月));
        /// 第46月存款應為: (第47個月的存款+3000)/(1+0.0171/12(月));
        ///  .....                    .....
        /// 第1個月存款應為: (第2個月的存款+3000)/(1+0.0171/12(月));
        /// </summary>
        public static void Fun3()
        {
            double[] money = new double[48];
            money[47] = 3000;
            double rate = 0.0171;
            for (int i = 46; i >= 0; i--)
            {
                money[i] = (money[i + 1] + 3000) / (1 + rate / 12);
            }
            for (int i = 47; i >= 0; i--)
            {
                Console.WriteLine($"第{i+1}個月的合計為:{money[i]}");
            }
            
        }

        #endregion

· 遞迴思想 

· 概念:遞迴,說白了就是直接或者間接的呼叫自己的一種演算法。它是把求解問題轉化為規模較小的子問題,然後通過多次遞迴一直到可以得出結果的最小解,然後通過最小解逐層向上返回撥用,最終得到整個問題的解。總之遞迴可以概括為一句話就是:能進則進,不進則退

· 三要素:

·  遞迴中每次迴圈都必須使問題規模有所縮小。

·  遞迴操作的每兩步都是有緊密的聯絡,如在遞迴歸操作時,前一次的輸出就是後一次的輸入。

·  當子問題的規模足夠小時,必須能夠直接求出該規模問題的解,其實也就是必須要有結束遞迴的條件。

· 注意事項:

· 深層次的遞迴會涉及到頻繁進棧出棧和分配記憶體空間,所以執行效率比較低,當問題規模較大時,不推薦使用。

· 在遞迴過程中,每次呼叫中的引數,方法返回點,區域性變數都是存放在堆疊中的,如果當問題規模非常大時,容易造成堆疊溢位。

· 例子:階乘,十進位制轉二進位制

   

        #region 遞迴思想


        /// <summary>
        /// 求階乘
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static int Fact(int n)
        {
            if (n == 1)
            {
                return 1;
            }
            return n * Fact(n - 1);
        }

        /// <summary>
        /// 十進位制轉二進位制
        /// </summary>
        /// <param name="rtn"></param>
        /// <param name="num"></param>
        /// <returns></returns>
        public static string Convert10To2(ref string rtn, int num)
        {
            if (num == 0)
                return string.Empty;
            Convert10To2(ref rtn, num / 2);
            return rtn += num % 2;
        }
        #endregion

· 貪心思想

· 貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的是在某種意義上的區域性最優解

· 注意事項:

· 不能保證貪心所得出的解是整體最優的。

· 不能用來求最大解和最小解問題。

· 只能求滿足某些約束條件的可行解的範圍。

· 例子:揹包問題,找零錢

 

        #region 貪心思想

        /// <summary>
        /// 貪心演算法(又稱貪婪演算法)是指,在對問題求解時,總是做出在當前看來是最好的選擇。
        /// 也就是說,不從整體最優上加以考慮,他所做出的是在某種意義上的區域性最優解。
        /// </summary>
        public static Dictionary<decimal,int> ExChange(decimal num)
        {
            /*
             其實說到貪心,基本上都會提到“揹包問題”,這裡我就舉一個“找零錢的問題“,對的,找零錢問題是我們生活中一個活生生的貪心演算法
             的例子,比如我買了“康師傅來一桶方便麵”,給了10兩銀子,方便麵3.8兩,那麼收銀mm該找我6.2兩,現實中mm不自覺的就會用到貪心的行
             為給我找最少張幣,總不能我給mm一張,mm給我十幾張,那樣mm會心疼的。
             */
            var money = GetInit();
            int i = 0;
            while(true)
            {
                if(num < 0.05M)
                {
                    return money;
                }
                var max = money.Keys.ElementAt(i);//表示100元紙幣
                if(num >= max)
                {
                    money[max] = money[max] + 1;
                    num = num - max;
                }
                else
                {
                    if (num >= 0.05M && num < 0.1M)
                    {
                        money[0.1M] = money[0.1M] + 1;
                        num = 0.0M;
                        if (money[0.1M] * 0.1M + money[0.2M] * 0.2M + money[0.5M] * 0.5M == 1.0M)
                        {
                            money[0.1M] = 0;
                            money[0.2M] = 0;
                            money[0.5M] = 0;
                            money[1.0M] += 1;
                        }
                    }
                    else
                    {
                        i++;
                    }
                }
            }
        }

        static Dictionary<decimal, int> GetInit()
        {
            Dictionary<decimal, int> money = new Dictionary<decimal, int>();

            //key表示錢,value表示錢的張數
            money.Add(100.00M, 0);
            money.Add(50.00M, 0);
            money.Add(20.00M, 0);
            money.Add(10.00M, 0);
            money.Add(5.00M, 0);
            money.Add(2.00M, 0);
            money.Add(1.00M, 0);
            money.Add(0.50M, 0);
            money.Add(0.20M, 0);
            money.Add(0.10M, 0);

            return money;
        }

        #endregion

· 列舉思想

· 將問題的所有可能的答案一一列舉,然後根據條件判斷此答案是否合適,保留合適的,捨棄不合適的。

· 列舉是我們在無奈之後的最後一擊,那麼使用列舉時我們應該儘量遵守下面的兩個條件

· 1.地球人都不能給我找出此問題的潛在規律。

· 2.候選答案的集合是一個計算機必須能夠承受的。

        /// <summary>
        /// 百錢百雞演算法(用100元錢買100只雞,其中公雞5元一隻,母雞3元一隻,小雞3只1元)
        /// Math.DivRem(int a, int b, out int result);返回a/b的餘數,result接收餘數
        /// </summary>
        public static void Fun2()
        {
            int a = 0, b = 0, c = 0, p = 0;
            for (a = 1; a <= 19; a++)
            {
                for (b = 1; b <= 33; b++)
                {
                    c = 100 - a - b;
                    Math.DivRem(c, 3, out p);
                    if(((5 * a + 3 * b + c / 3) == 100) && p == 0)
                    {
                        Console.WriteLine($"a:{a}");
                        Console.WriteLine($"b:{b}");
                        Console.WriteLine($"c:{c}");
                        return;
                    }
                }
            }
        }

相關文章