動態規劃之合唱隊形問題

問題描述:java

  N 位同窗站成一排,音樂老師要請其中的(N-K)位同窗出列,而不改變其餘同窗的位置,使得剩下的K位同窗排成合唱隊形。合唱隊形要求:設K位同窗從左到右 依次編號爲1,2…,K,他們的身高分別爲T1,T2,…,TK,則他們的身高知足 T1<T2...<Ti>Ti+1>…>TK(1<=i<=K)。已知全部N位同窗的身高,計算最少須要幾位 同窗出列,可使得剩下的同窗排成最長的合唱隊形。 app

問題分析:spa

  假設第i位同窗爲個子最高的同窗,咱們先對其左邊的同窗求最大上升子序列,再對其右邊的同窗求最大降低子序列,而後二者相加再減1(第i位同窗被重複計算 了一次),便獲得第i位同窗爲最高個時所能排成的最長合唱隊形。若是咱們對這N位同窗都執行此操做,即可獲得每位同窗爲最高個時所能排成的最長合唱隊形, 選取其中最長的合唱隊形做爲最終的結果。  .net

 從 上述的分析能夠看出,咱們能夠將問題分紅互相不獨立的子問題,只要獲得子問題的最優解,即可獲得整個問題的最優解。咱們能夠用一張表來記錄全部已解決問題 的答案,從而避免了重複計算。這裏的一個關鍵問題即是:如何獲得第i位同窗的最大上升子序列和最大降低子序列。假如這N位同窗的身高分別 爲:176,163,150,180,170,130,167,160,咱們用up[i]來記錄第i位同窗的最大上升子序列。若是要獲得180同窗爲最高 個時的最大上升子序列即up[4],咱們只需求出前3位同窗所能造成的最大上升子序列,將其加1便可;要獲得前3位同窗所造成的最大上升子序列,便要求得 前2位同窗的最大上升子序列,再加上1便可;一樣要獲得前2位同窗的最大上升子序列,便要求得第1位同窗的最大上升子序列。所以這是一個遞推關係,只要我 們將前i個同窗爲最高個時作造成的最大上升子序列的值記錄下來,取其中最大值加1即可獲得第i位同窗的最大上升子序列即up[i]。同理咱們用 down[i]來記錄第i位同窗的最大降低子序列,只要咱們將後(N-i)位同窗每位同窗爲最高個時的最大降低子序列記錄下來,取其中最大者再加1即可得 到第i位同窗爲最高個時的最大降低子序列即down[i]。那麼,第i位同窗爲最高個時作能造成的最長合唱隊形的長度爲up[i]+down[i]-1。 求得全部同窗爲最高個時所能造成的最長合唱隊形的長度,取其中最大值爲最終的結果。blog

[java] view plain copy索引

 

  1. public class Main {  
  2.     public static void main(String[] args) {  
  3.         int []high={176,163,150,180,170,130,167,160};  
  4.         int []up=new int[8];   //記錄每位同窗的最大上升子序列  
  5.         int []down=new int[8]; //記錄每位同窗的最大降低子序列  
  6.         for(int i=0;i<high.length;i++){  
  7.             up[i]=1; //每位同窗的最大上升子序列初始值爲1  
  8.             for(int j=0;j<i;j++){  
  9.                 if((high[j]<high[i])&&(up[i]<up[j]+1)) up[i]=up[j]+1; //前i位同窗的最大上升子序列的最大值再加1  
  10.             }  
  11.         }  
  12.         for(int i=high.length-1;i>=0;i--){  
  13.             down[i]=1;  
  14.             for(int j=high.length-1;j>i;j--){  
  15.                 if((high[j]<high[i])&&(down[i]<down[j]+1)) down[i]=down[j]+1; //後N-i位同窗的最大降低子序列的最大值再加1  
  16.             }  
  17.         }  
  18.         int max=0; //設每位同窗所造成的最長合唱隊形的最大值初值爲0  
  19.         int index=0; //設最大值對應的索引爲0  
  20.         for(int i=0;i<high.length;i++){  
  21.             if(up[i]+down[i]-1>max) {  
  22.                 max=up[i]+down[i]-1; //求得每位同窗所造成的最長合唱隊形的最大值  
  23.                 index=i;  //求得對應的索引  
  24.             }  
  25.         }  
  26.         System.out.println("最長合唱隊形的長度爲:"+max);  
  27.         System.out.println("對應的是第"+(index+1)+"位同窗,須要"+(high.length-max)+"位同窗出列");  
  28.   
  29.     }  
  30. }
相關文章
相關標籤/搜索