leetcode动态规划第三期

来源:互联网 发布:mac如何删除重复照片 编辑:程序博客网 时间:2024/04/19 15:16

之前漏了一题是leetcode的115题,S子序列包含T的种类

public class 动态规则之S子序列包含T的种类_115 { public int numDistinct(String s, String t) {int lenS=s.length();int lenT=t.length();//s从0-i截取字符串的子串包含t的种类个数int [][] dp=new int[lenS+1][lenT+1];//两个都为空时候,s包含t,只有一种情况dp[0][0]=1;//t为空串时候,只有一种情况for (int i = 1; i <lenS; i++) {dp[i][0]=1;} //s为空串时候,为0中情况for (int i = 1; i <lenT; i++) {dp[0][i]=0;}for (int i = 1; i <=lenS; i++) {for (int j = 1; j <=lenT; j++) {dp[i][j]=dp[i-1][j];if (s.charAt(i-1)==t.charAt(j-1)) {dp[i][j]+=dp[i-1][j-1];}}}return dp[lenS][lenT]; }}

还有几种Dp情况,我在列举01背包问题,例如华为机试题:购物单--链接:

http://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4?tpId=37&tqId=21239&rp=&ru=/ta/huawei&qru=/ta/huawei/question-ranking

package com.example.oj;import java.util.Scanner; public class 动态规划之0_1背包问题{     public static void main(String[] args) {        Scanner sc=new Scanner(System.in);        int sum_money = 0;        int num = 0;                   sum_money=sc.nextInt();        num=sc.nextInt();        int price[]=new int[num+1];        int val[]=new int[num+1];        int[] q = new int[num+1];        for (int i = 1; i <= num; i++) {            price[i]=sc.nextInt();            val[i]=sc.nextInt()*price[i];            q[i]=sc.nextInt();        }        int[][] dp=new int[num+1][sum_money+1];/** 初始值java默认赋值为0,其中dp[0][0...sum_money]为0,从dp[1][0...sum_money]  计算第1行,代表第一件物品dp[i][sum_money] : 前i个物体放入容量为sum_money的背包的最大价值;dp[i-1][sum_money] : 前i-1个物体放入容量为sum_money的背包的最大价值;dp[i-1][sum_money-price[i]] : 前i-1个物体放入容量为sum_money-price[i]的背包的最大价值;dp[i][sum_money]=Math.max{dp[i-1][sum_money-price[i]]+val[i] , dp[i-1][sum_money]}*/        for (int i = 1; i <=num; i++) {            for (int j = 1; j <= sum_money; j++) {                if(q[i]==0)                {                    if(price[i]<=j)                        dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-price[i]]+val[i]);                }                if(q[i]>0)                {                    if(price[i]+price[q[i]]<=j)                        dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-price[i]-price[q[i]]]+val[i]+val[q[i]]);                }            }                     }        System.out.println(dp[num][sum_money]);    } }
还有什么最长公共子串,最长公共子序列问题:

package com.example.oj;public class 动态规划之最长公共连续子串 {public static void main(String[] args) {动态规划之最长公共连续子串 test = new 动态规划之最长公共连续子串();        String A="binghaven";        String B="jingseven";int lcString = getLCString(A,A.length(),B,B.length());System.out.println(lcString);}private static int getLCString(String a, int n, String b, int m) {char[] charA = a.toCharArray();char[] charB= b.toCharArray();//必须以dp[i][j]中charA[i]和charB【j】为结尾的最长子串int [][]dp=new int [n][m];String [][]dpStr=new String[n][m];for (int i = 0; i <n; i++) {for (int j = 0; j < m; j++) {dpStr[i][j]="";}}for (int i = 0; i < n; i++) {if (charA[i]==charB[0]) {dp[i][0]=1;dpStr[i][0]=""+charA[i];}}for (int i = 0; i < m; i++) {if (charA[0]==charB[i]) {dp[0][i]=1;dpStr[0][i]=""+charB[i];}}for (int i = 1; i < n; i++) {for (int j = 1; j < m; j++) {if (charA[i]==charB[j]) {dp[i][j]=dp[i-1][j-1]+1;dpStr[i][j]=dpStr[i-1][j-1]+charA[i];}}}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (dp[i][j]==dp[n-1][m-1]) {System.out.println(dpStr[i][j]);}}}return dp[n-1][m-1];}}
可以打印出来最长的子串哦!

package com.example.oj;public class 动态规划之最长公共子序列 {public static void main(String[] args) {//保留空字符串是为了getLength()方法的完整性也可以不保留      //但是在getLength()方法里面必须额外的初始化c[][]第一个行第一列  String x="ABCBDAB";String y="ABCBDAB";    int [][] b=getLength(x,y);    getMaxLenString(b,x,y);}    private static void getMaxLenString(int[][] dp, String x, String y) {String res="";int startX=x.length();int startY=y.length();while (startX>=1&&startY>=1) {if (dp[startX][startY]==dp[startX-1][startY-1]+1) {res=x.charAt(startX-1)+res;startX--;startY--;}else if (dp[startX][startY]==dp[startX-1][startY]) {startX--;}else if (dp[startX][startY]==dp[startX][startY-1]) {startY--;}}System.out.println(res);}private static int[][] getLength(String x, String y) {    char[] charX = x.toCharArray();    char[] charY = y.toCharArray();    //dp[i][j]表示以char[0--i-1]和char[0--j-1]最长公共子序列    //dp[0][0]表示两个都是空串,直接为0;    int dp[][]=new int[charX.length+1][charY.length+1];    for (int i = 0; i <=charX.length; i++) {        dp[i][0]=0;}    for (int i = 0; i <=charY.length; i++) {    dp[0][i]=0;}    for (int i =1; i <=charX.length; i++) {for (int j = 1; j <=charY.length; j++) {if (charX[i-1]==charY[j-1]) {dp[i][j]=dp[i-1][j-1]+1;}else {dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);}}}    System.out.println(dp[charX.length][charY.length]);return dp;}}
回溯法输入最长的子序列!

还有一个是博弈问题:

public class 动态规划之博弈问题 {//递归版本public int  win(int [] arr) {if (arr==null||arr.length==0) {return 0;}return Math.max(f(arr,0,arr.length-1), s(arr,0,arr.length-1));}    //后拿情况下的最大值private int s(int[] arr, int i, int j) {if (i==j) {return 0;}return Math.min(f(arr, i+1, j), f(arr, i, j-1));}//从 i 到j情况下拿到的值的最大值;    //先拿情况下,等拿完之后就会变为后拿情况private int f(int[] arr, int i, int j) {if (i==j) {return arr[i];}//返回从i+1到j后拿情况+arr[i]和从i到j-1后拿情况下+arr[j]的两者取最大值就可以了return Math.max(arr[i]+s(arr, i+1, j), arr[j]+s(arr, i, j-1));}//动态规划版本public int  win2(int[] arr) {if (arr==null||arr.length==0) {return 0;}//首选从i-j中选出来的最大值int[][] f=new int[arr.length][arr.length];//次选从i-j选出来的最大值int[][] s=new int[arr.length][arr.length];    for (int j = 0; j < arr.length; j++) {    //只有首选能选到的情况f[j][j]=arr[j];for (int i = j-1; i>=0; i--) {f[i][j]=Math.max(arr[i]+s[i+1][j], arr[j]+s[i][j-1]);s[i][j]=Math.min(f[i+1][j], f[i][j-1]);}}    return Math.max(f[0][arr.length-1], s[0][arr.length-1]);}}
好了,目前碰到过的DP就这么多了,说多不多,说少还真不少哎。。。




0 0