1. 程式人生 > 實用技巧 >演算法模板:貪心

演算法模板:貪心

  1. 貪心:

    • 原理:區域性選擇最優解,當前選擇對後續不產生影響

    • 基本思路:

      ① 建立數學模型來描述問題

      ② 分解為若干子問題

      ③ 依序對每一個子問題求最優解(下一個包含上一個的最優解)

      ④ 把所有子問題的區域性最優解合併為原問題的一個解

    1. 活動安排問題

      • 會場安排活動:即按活動的結束時間排序,讓剩餘時間最大化,安排更多的活動

      • 程式碼:

        bool cmp1(node a, node b)
        {
            return a.end < b.end ;      //結束時間從小到大排序
        }
        
        sort(Num+1, Num+n+1, cmp1);
        
        for(int i=2; i<=n; i++)
            {
                if(Num[i].begin >= Num[1].end)
                {
                    Num[1].end = Num[i].end ; //更新結束時間 
                    count++;            
                }       
            }
        
      • 活動安排會場:按活動的開始時間排序,如果時間衝突則加一個會場

      • 程式碼:

        bool cmp(node a,node b) {
            return a.start < b.start;
        }
        
        sort(Num,Num+n,cmp);
        
        b[0]=p[0].end ;
        sum = 1;
        for(i=1; i<n; i++)
        {
           for(j=0; j<sum; j++)
           {
              if(b[j] <= p[i].start )//找到房間,更新結束時間
              {
                 b[j]=p[i].end ;
                 break;
              }      
           }
           if(j==sum)//未找到房間,更新結束時間
           {
              b[sum]=p[i].end ;
              ++sum;
           }
        }
        
    2. 找零錢問題:

      • 問題描述:找錢,有幾種不同面值的貨幣,求最少使用多少張

      • 策略:優先使用面值大的貨幣

      • 程式碼:

        int num = 4; //4種 
        int m[] = {25,10,5,1}; //面值
        int target = 99; //要找
        int count[4]; //記錄每種面值需多少
        for(int i=0; i<num; i++) {
        	count[i] = target / m[i];
        	target = target % m[i];
        }
        
    3. 揹包問題:

      • 問題描述:一堆物品,在負重允許下取最高價值
      • 策略:
        1. 優先選擇價值最大者(value)
        2. 優先選擇重量最小者(weight)
        3. 優先選擇價效比最高者(value / weight)
      • 以上三者無具體情況無法確定究竟是哪種策略最優
    4. 均分紙牌:

      • 問題描述:N堆紙牌,從任一堆上去任意張到臨邊牌堆,最少多少次使牌堆一樣多

      • 策略:每次都考慮從i牌堆取來a[i]-avg張牌使a[i+1]達到均值

      • 程式碼:

        for(int i=0; i<n-1; i++) {
            if(a[i] != avg ) {
                int move = a[i] - avg;
                a[i] -= move;
                a[i+1] += move;
                times ++;
            }
        }