算法:貪婪算法基礎

算法:貪婪算法基礎

理解貪心算法

說明

  貪心算法是使所作的選擇看起來都是當前最佳的,指望經過所作的局部最優選擇來產生一個全局最優解java

設計貪心算法的步驟

  1.將優化問題轉換成這樣一個問題,即先作出選擇,再解決剩下的一個子問題算法

  2.證實原問題老是有一個最優解是貪心選擇的獲得的,從而說明貪心選擇的安全。安全

  3.說明在作出貪心選擇後,剩下的子問題具備這樣一個性質。即若是將子問題的最優解和咱們所作的貪心選擇聯合起來,能夠獲得一個更加負責的動態規劃解。優化

 

剪繩子

問題描述

  給你一個長度爲n的繩子,請把繩子剪成m段(m,n都是整數,且都大於1)每段繩子的長度即爲K[0],K[1],K[2]...K[m]。請問K[0]*k[1]..*k[m]可能的最大乘積是多少spa

解決思路

  若是咱們按照以下的策略剪繩子,則獲得的各段繩子的長度的乘積將最大;當n>=5,咱們儘量地剪長度爲3的繩子;當剩下的繩子長度爲4時,把繩子剪爲長度爲2的繩子.設計

  貪心算法的核心是經過局部最優解來獲得全局最優解,對於分割問題來講,要使乘積最大,該問題的貪心思想是儘量去剪爲長度爲3的繩子!blog

Java代碼

迭代法排序

    public static int greedy_cut_rope_1(int n)
    {
        if(n<2)
            return 0;
        if(n==2)
            return 1;
        if(n==3)
            return 2;
        //儘量多地去減長度爲3的繩子段
        int timesOf3 = n/3;
        //當繩子最後剩下的長度爲4的時候,不能再去剪去長度爲3的繩子段
        if(n-timesOf3*3==1)
            timesOf3-=1;
        int timesOf2 =(n-timesOf3*3)/2;
        return (int) (Math.pow(3,timesOf3)*Math.pow(2,timesOf2));
    }

遞歸法遞歸

    public static int greedy_cut_rope(int n)
    {
        if(n==2)
            return 2;
        if(n==3)
            return 3;
        if(n<2)
            return 1;
        //int timesOf3 = n/3;
        if(n==4)
            return 4;
        return 3*greedy_cut_rope(n-3);
    }

 

揹包問題

問題描述

  給定N個物品和一個容量爲C的揹包,物品i的重量爲Wi,其價值爲Vi,揹包問題是如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大。注意在揹包問題中,能夠將某種物品的一部分裝入揹包中,可是不能夠重複裝入。資源

解決思路

三種貪心思想:

  •   選擇價值最大的物品
  •   選擇重量最輕的物品
  •   選擇單位重量價值最大的物品

毫無疑問,咱們固然選擇第三種咯。先把性價比最高的所有裝入,最後不足所有裝入的部分裝入。

Java實現代碼

    public static int greedy_knapSack(int[] w,int[] v,int n,int c)
    {
        //  假設物品已按單位重量降序排列
        double[] x = new double[10];
        int maxValue =0;
        int i;
        for(i=0;w[i]<c;i++)
        {
            x[i]=1; //將物品 i 裝入揹包
            maxValue+=v[i];
            c=c-w[i]; // 揹包剩餘數量
        }
        x[i]=(double)c/w[i];    //物品i裝入一部分
        maxValue+=x[i]*v[i];
        return maxValue;    //返回揹包得到的價值
    }

 

活動選擇問題

問題描述

  假設有一個須要使某一資源的n個活動組成的集合S={a1,a2,a3...an}。該資源一次只能被一個活動佔用,每一個活動ai有一個開始時間Si和結束時間Fi,且0<=Si<Fi<∞。一旦被選擇後,活動ai就佔據半開時間區間[Si,Fi)。若是區間[Si,Fi)與 [Sj,Fj)互不重疊,稱活動ai與aj是兼容的。活動選擇問題就是要選擇出一個由互相兼容的問題組成的最大集合

  討論下面的活動集合S,其中各活動已按結束時間的單調遞增順序進行了排序:

  

解決思路

  對於任意非空子問題Sij,設am是Sij中具備最先結束時間的活動:

    fm=min{fk:ak∈Sij}

  那麼:

1.活動am在Sij的某最大兼容活動子集中被使用。

2.子問題Sim爲空,因此選擇am使子問題Smj爲惟一可能非空的子問題

  在解決子問題時,選擇am是一個可被合法調度、具備最先結束時間的活動。從直覺上來看,這種活動選擇方法是一種貪婪技術,他給後面剩下的待調度任務留下了儘量多的機會。也就是說,此處的貪心選擇使得剩下的、未調度的時間最大化。

Java實現代碼

迭代貪心算法

    public static void greedy_activity_selector(int[] s,int[] f,boolean[] b)
    {
        int n = s.length-1;
        b[1]=true;
        int j=1;
        for(int i =2;i<=n;i++)
        {
            if(s[i]>f[j])
            {
                b[i]=true;
                j=i;
            }else
                b[i]=false;
        }
        for(int i=1;i<b.length;i++)
            System.out.println(b[i]);
    }
相關文章
相關標籤/搜索