日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动态规划算法入门---java版

發布時間:2024/1/23 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态规划算法入门---java版 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載:http://blog.csdn.net/p10010/article/details/50196211

?

動態規劃算法(后附常見動態規劃為題及Java代碼實現)


一、基本概念

?? ?動態規劃過程是:每次決策依賴于當前狀態,又隨即引起狀態的轉移。一個決策序列就是在變化的狀態中產生出來的,所以,這種多階段最優化決策解決問題的過程就稱為動態規劃。

二、基本思想與策略

?? ?基本思想與分治法類似,也是將待求解的問題分解為若干個子問題(階段),按順序求解子階段,前一子問題的解,為后一子問題的求解提供了有用的信息。在求解任一子問題時,列出各種可能的局部解,通過決策保留那些有可能達到最優的局部解,丟棄其他局部解。依次解決各子問題,最后一個子問題就是初始問題的解。

?? ?由于動態規劃解決的問題多數有重疊子問題這個特點,為減少重復計算,對每一個子問題只解一次,將其不同階段的不同狀態保存在一個二維數組中。

?? ?與分治法最大的差別是:適合于用動態規劃法求解的問題,經分解后得到的子問題往往不是互相獨立的(即下一個子階段的求解是建立在上一個子階段的解的基礎上,進行進一步的求解)

以上都過于理論,還是看看常見的動態規劃問題吧!!!

三、常見動態規劃問題

?? 1、找零錢問題

?? 有數組penny,penny中所有的值都為正數且不重復。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定一個整數aim(小于等于1000)代表要找的錢數,求換錢有多少種方法。
給定數組penny及它的大小(小于等于50),同時給定一個整數aim,請返回有多少種方法可以湊成aim。
測試樣例:
[1,2,4],3,3
返回:2

解析:設dp[n][m]為使用前n中貨幣湊成的m的種數,那么就會有兩種情況:

???????????? 使用第n種貨幣:dp[n-1][m]+dp[n-1][m-peney[n]]

????????????? 不用第n種貨幣:dp[n-1][m],為什么不使用第n種貨幣呢,因為penney[n]>m。

??????? 這樣就可以求出當m>=penney[n]時 dp[n][m] = dp[n-1][m]+dp[n-1][m-peney[n]],否則,dp[n][m] = dp[n-1][m]

代碼如下:

[java]?view plaincopy
  • <span?style="font-size:18px;">import?java.util.*;??
  • ??
  • public?class?Exchange?{??
  • ????public?int?countWays(int[]?penny,?int?n,?int?aim)?{??
  • ????????//?write?code?here??
  • ????????if(n==0||penny==null||aim<0){??
  • ?????????return?0;?????
  • ????????}??
  • ????????int[][]?pd?=?new?int[n][aim+1];??
  • ????????for(int?i=0;i<n;i++){??
  • ?????????pd[i][0]?=?1;?????
  • ????????}??
  • ????????for(int?i=1;penny[0]*i<=aim;i++){??
  • ?????????pd[0][penny[0]*i]?=?1;?????
  • ????????}??
  • ????????for(int?i=1;i<n;i++){??
  • ????????????for(int?j=0;j<=aim;j++){??
  • ????????????????if(j>=penny[i]){??
  • ????????????????????pd[i][j]?=?pd[i-1][j]+pd[i][j-penny[i]];??
  • ????????????????}else{??
  • ????????????????????pd[i][j]?=?pd[i-1][j];??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ????????return?pd[n-1][aim];??
  • ????}??
  • }</span>??

  • 2、走方格問題

    ? 有一個矩陣map,它每個格子有一個權值。從左上角的格子開始每次只能向右或者向下走,最后到達右下角的位置,路徑上所有的數字累加起來就是路徑和,返回所有的路徑中最小的路徑和。
    給定一個矩陣map及它的行數n和列數m,請返回最小路徑和。保證行列數均小于等于100.
    測試樣例:
    [[1,2,3],[1,1,1]],2,3
    返回:4

    解析:設dp[n][m]為走到n*m位置的路徑長度,那么顯而易見dp[n][m] = min(dp[n-1][m],dp[n][m-1]);

    ?

    代碼如下:

    [java]?view plaincopy
  • <span?style="font-size:18px;">import?java.util.*;??
  • ??
  • public?class?MinimumPath?{??
  • ????public?int?getMin(int[][]?map,?int?n,?int?m)?{??
  • ????????//?write?code?here??
  • ???????int[][]?dp?=?new?int[n][m];??
  • ????????for(int?i=0;i<n;i++){??
  • ????????????for(int?j=0;j<=i;j++){??
  • ?????????????dp[i][0]+=map[j][0];??????
  • ????????????}??
  • ????????}??
  • ????????for(int?i=0;i<m;i++){??
  • ????????????for(int?j=0;j<=i;j++){??
  • ?????????????dp[0][i]+=map[0][j];??????
  • ????????????}??
  • ????????}??
  • ????????for(int?i=1;i<n;i++){??
  • ????????????for(int?j=1;j<m;j++){??
  • ?????????????dp[i][j]?=?min(dp[i][j-1]+map[i][j],dp[i-1][j]+map[i][j]);?????
  • ????????????}??
  • ????????}??
  • ????????return?dp[n-1][m-1];??
  • ????}??
  • ????public?int?min(int?a,int?b){??
  • ????????if(a>b){??
  • ?????????return?b;?????
  • ????????}else{??
  • ?????????return?a;?????
  • ????????}??
  • ????}??
  • }</span>??

  • 3、走臺階問題

    有n級臺階,一個人每次上一級或者兩級,問有多少種走完n級臺階的方法。為了防止溢出,請將結果Mod 1000000007
    給定一個正整數int n,請返回一個數,代表上樓的方式數。保證n小于等于100000。
    測試樣例:
    1
    返回:1

    解析:

    這個問題典型的斐波那契數列問題。
    假設N級樓梯的爬法有A(N)種方法,假設第一步上一個臺階,則上法有A(N-1)種,如果第一步上兩個臺階,則上法有A(N-2)種方法,因此:
    A(N)=A(N-1)+A(N-2)
    而A(1)=1,A(2)=2,則A(3)=A(1)+A(2)=3,A(4)=A(2)+A(3)=5,……
    從而可以遞推出N階臺階時的方法。

    這是一個非常經典的為題,設f(n)為上n級臺階的方法,要上到n級臺階的最后一步有兩種方式:從n-1級臺階走一步;從n-1級臺階走兩步,于是就有了這個公式f(n) = f(n-1)+f(n-2);

    代碼如下:

    [java]?view plaincopy
  • <span?style="font-size:18px;">import?java.util.*;??
  • ??
  • public?class?GoUpstairs?{??
  • ????public?int?countWays(int?n)?{??
  • ????????//?write?code?here??
  • ????????if(n<=2)??
  • ????????????return?n;??
  • ????????int?f?=?1%1000000007;??
  • ????????int?s?=?2%1000000007;??
  • ????????int?t?=?0;??
  • ????????for(int?i=3;i<=n;i++){??
  • ?????????t?=?(f+s)%1000000007;??
  • ?????????f?=?s;??
  • ?????????s?=?t;??
  • ????????}??
  • ???????return?t;???
  • ????}??
  • }</span>??

  • 4、最長公共序列數

    給定兩個字符串A和B,返回兩個字符串的最長公共子序列的長度。例如,A="1A2C3D4B56”,B="B1D23CA45B6A”,”123456"或者"12C4B6"都是最長公共子序列。
    給定兩個字符串A和B,同時給定兩個串的長度n和m,請返回最長公共子序列的長度。保證兩串長度均小于等于300。
    測試樣例:
    "1A2C3D4B56",10,"B1D23CA45B6A",12
    返回:6

    解析:設dp[n][m] ,為A的前n個字符與B的前m個字符的公共序列長度,則當A[n]==B[m]的時候,dp[i][j] = max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]),否則,dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);

    代碼如下:

    [java]?view plaincopy
  • <span?style="font-size:18px;">import?java.util.*;??
  • ??
  • public?class?LCS?{??
  • ????public?int?findLCS(String?A,?int?n,?String?B,?int?m)?{??
  • ????????//?write?code?here??
  • ????????int[][]?dp?=?new?int[n][m];??
  • ????????char[]?a?=?A.toCharArray();??
  • ????????char[]?b?=?B.toCharArray();??
  • ???????for(int?i=0;i<n;i++){??
  • ???????????if(a[i]==b[0]){??
  • ???????????????dp[i][0]?=?1;??
  • ???????????????for(int?j=i+1;j<n;j++){??
  • ???????????????????dp[j][0]?=?1;??
  • ???????????????}??
  • ???????????????break;??
  • ???????????}??
  • ?????????????
  • ???????}??
  • ?????????for(int?i=0;i<m;i++){??
  • ???????????if(a[0]==b[i]){??
  • ???????????????dp[0][i]?=?1;??
  • ???????????????for(int?j=i+1;j<m;j++){??
  • ???????????????????dp[0][j]?=?1;??
  • ???????????????}??
  • ???????????????break;??
  • ???????????}??
  • ?????????????
  • ???????}??
  • ???????for(int?i=1;i<n;i++){??
  • ???????????for(int?j=1;j<m;j++){??
  • ???????????????if(a[i]==b[j]){??
  • ??????????????????dp[i][j]?=?max(dp[i-1][j-1]+1,dp[i-1][j],dp[i][j-1]);??
  • ???????????????}else{??
  • ???????????????????dp[i][j]?=?Math.max(dp[i-1][j],dp[i][j-1]);??
  • ???????????????}??
  • ?????????????????????
  • ???????????}??
  • ???????}???
  • ??????????
  • ????????return?dp[n-1][m-1];??
  • ????}??
  • ????public?int?max(int?a,int?b,int?c){??
  • ????????int?max?=?a;??
  • ????????if(b>max)??
  • ????????????max=b;??
  • ????????if(c>max)??
  • ????????????max?=?c;??
  • ????????return?max;??
  • ????}??
  • }</span> ?

  • 總結

    以上是生活随笔為你收集整理的动态规划算法入门---java版的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。