動態規劃(二)
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);
}
}
截圖: