1. 程式人生 > >動態規劃(二)

動態規劃(二)

1.以所經過的權值之和最大值為例進行說明。

行進的過程中,每次只有兩種選擇:向左或向右。一個有n層的數字三角形的完整路徑有2n條,所以當n比較大的時候,搜尋全部路徑,從中找出最大值,效率較低。

採用動態規劃方法實現。

d(i,j)表示從位置(i,j)出發時得到的最大值(包括位置(i,j)本身),可以寫出最大值的遞迴方程:

由於遞迴方程中包含了重複子問題,直接採用遞迴方程求解, 效率較低。採用動態規劃的方法,用一張二維表記錄中間過程的值,可以把時間效率提高到n2。

程式碼:

import java.util.Scanner;

public class ShuTa {

    void TheBest(int a[][],int n,int m){

     int b[][]=new int[m][n];

     int c[][]=new int[m][n];

     for(int i=0;i<n;i++){

     for(int j=0;j<m;j++){

     b[i][j]=a[i][j];

     }

     }

     for(int i=n-2;i>=0;i--){

     for(int j=0;j<=i;j++)

     {

     if(a[i+1][j]>a[i+1][j+1])

     {

     a[i][j]=a[i][j]+a[i+1][j];

     c[i][j]=0;//b表示向下走

     }

     else

     {

     a[i][j]=a[i][j]+a[i+1][j+1];

     c[i][j]=1; //表示向右下方走

     }

     }

     }

     int j=0;

     System.out.print("輸出最大值為:");

     System.out.println(a[0][0]);

     for(int i=0;i<n;i++)

     {

     System.out.print(b[i][j]+"->");

     j=j+c[i][j];

     }

    }

public static void main(String[] args) {

int x[][]=new int[5][5];

  Scanner scanner=new Scanner(System.in);

  for(int i=0;i<5;i++){

  for(int j=0;j<5;j++){

  x[i][j]=scanner.nextInt();

   x[i][j]=x[i][j];

  }

  }

      ShuTa sh=new ShuTa();

      sh.TheBest(x, 5, 5);

}

}

截圖:

用f[i]表示以ai為結尾的最長上升子序列的長度,可建立如下遞迴方程:

  

f[ ]是單調遞增的,因為如果有i<j且f[i]>=f[j],那麼f[i]必定可以被f[j]的內容所更新。

每處理到一個ai,要找到一個k滿足f[k–1]<ai且f[k]>= ai,並用ai更新f[k],最終max{k|f[k]!=∞}就是答案。

程式碼:

      public class LIS {

     void lis(int A[],int n){

 int i,j;

 int f[]=new int [A.length];

 int len=1;

 for( i=0;i<n;i++){

 f[i]=1;

 for(j=0;j<i;j++){

 if(A[j]<=A[i]&&(f[j]+1>=f[i]))

 f[i]=f[j]+1;

 }

 if(f[i]>len){

 len=f[i];

 }

 }

 System.out.print("最長上升子序列的長度為:");

 System.out.println(len);

     }

public static void main(String[] args) {

int X[]=new int[10];

Scanner scanner=new Scanner(System.in);

System.out.print("輸入一組數為:");

for(int i=0;i<10;i++){

X[i]=scanner.nextInt();

}

        LIS ls=new LIS();

        ls.lis(X, 10);

}

}

截圖: