动态规划——在做题中理解你的美

来源:互联网 发布:知乎补充回答 编辑:程序博客网 时间:2024/05/17 05:11

一、求数组最大子数组和
子数组必须是连续的,数组中可能包含有:正整数,零,负整数三种中的一种或多种。
方法一:可以用普通的方法枚举所有的连续子数组,然后求出最大的子数组和,时间复杂度为O(n*n)。
方法二:动态规划!
方法一代码:

int MaxSubString(int[] A, int n){  int max = min;  //初始值为负无穷大  int sum;  for(int i = 0; i < n; i++)  {    sum = 0;    for(int j = i; j < n; j++)    {      sum += A[j];      if(sum > max)        max = sum;    }  }  return max;}

方法二代码:

import java.util.Scanner;public class BigSubArraySum {    public static void main(String[] args) {        Scanner input = new Scanner(System.in);        System.out.println("请输入n个整数");        int n = input.nextInt();        int[] arr = new int[n];        for (int i = 0; i < n; i++) {            arr[i] = input.nextInt();        }        int max = arr[0];        int currentMax = arr[0];        for (int i = 1; i < arr.length; i++) {            //currentMax = (currentMax >= 0) ? arr[i] + currentMax : arr[i];            currentMax = Math.max(arr[i] + currentMax,arr[i]);            max = Math.max(max, currentMax);        }        System.out.println(max);    }}

数组: {0, -2, 3, 5, -1, 2} 返回值为 9,因为连续子数组3+5-1+2=9>3+5=8;

二、硬币问题
(还是有问题,当货币中为2,3,4或者其他就会出现bug,待解决)

public class MinCoins {    public static void main(String[] args) {        int[] coins = {1,3,5};      //coins数组存放各个无重复面值        int value = 17;                 //value表示需要凑成的钱数        int[] jilu = new int[value];    //记录每一步的面值        int min = new MinCoins().solution(coins, value, jilu);        for (int i = value - 1; i >= 0;) {            System.out.print(jilu[i] + "->");            i = i - jilu[i];//倒序输出每一步用的哪种币        }        System.out.println();        System.out.println(min);    }    private int solution(int[] coins, int value, int[] jilu) {        int[] mins = new int[value + 1];    //数组mins表示凑成多少钱所需最小钱币数目,为了使索引能达到value,加1        mins[0] = 0;                        //凑成0元所需0个        for (int i = 1; i <= value; i++)    //将数组中的数初始化为最大值            mins[i] = Integer.MAX_VALUE;        for (int i = 1; i <= value; i++) {  //从凑1元钱开始,递增直至value            for (int j = 0; j < coins.length; j++) {//j表示第(j+1)种币                if (coins[j] <= i) {                      //意思是比较所有种类的币是不是比所要凑的值小,                    //如若比要凑得值还大就跳过比下一种币                    mins[i] = Math.min(mins[i] , mins[i - coins[j]] + 1);                    //将满足coins[j] <= i的coins[j]遍历一遍,则mins[i]存储的值就是几种情况中的最小值                    jilu[i - 1] = coins[j];//记录每步所使用的币值                }            }        }        return mins[value];    }}

三、背包问题
w[i] : 第i个物体的重量;
p[i] : 第i个物体的价值;
arr[i][m] : 前i个物体放入容量为m的背包的最大价值;
arr[i-1][m] : 前i-1个物体放入容量为m的背包的最大价值;
arr[i-1][m-w[i]] : 前i-1个物体放入容量为m-w[i]的背包的最大价值;
由此可得:
arr[i][m]=max{arr[i-1][m-w[i]]+p[i] , arr[i-1][m]}

public class BackPack {    public static void main(String[] args) {        int[] w = { 3, 4, 5 };//每个货物的重量        int[] p = { 4, 5, 6 };//每个货物的价值(与上面对应)        int m=10;               //背包最大承重        int n=w.length;        int[][] arr=new int[n+1][m+1];//定义二维数组存储每种情况下背包里的物品价值           int i,j;        for(i=0;i<=n;i++){      //将前(i+1)个物品放入承重为0的包里价值为0            arr[i][0]=0;        }        for(j=0;j<=m;j++){      //将前0个物品放入承重为j的包里价值为0            arr[0][j]=0;        }        for(j=0;j<=m;j++){      //j表示背包承重(从0递增至m)            for(i=1;i<=n;i++){  //i表示第i个货物                if(j<w[i-1]){   //如果第i个货物的重量w[i-1]大于背包承重则舍弃这个货物                    arr[i][j]=arr[i-1][j];                }else{          //如果第i个货物的重量w[i-1]小于背包承重则取两者之间最大值                    arr[i][j]=Math.max(arr[i-1][j-w[i-1]]+p[i-1],arr[i-1][j]);                }//或许你会问为什么取最大,加入第i个肯定比不加大呀!你说的没错但是你必须考虑能不能加,至于能不能加交给它前面的去考虑,这也是动态规划的思想之一            }        }        System.out.println(arr[n][m]);    }}

四、最长公共子序列
这里写图片描述

public class LCS {    public static void main(String[] args) {        String str1="ABCDABDC";        String str2="BBCDCADBCAD";        char[] ch1=str1.toCharArray();        char[] ch2=str2.toCharArray();        int m=ch1.length;        int n=ch2.length;        int[][] arr=new int[m+1][n+1];        int i,j;        for(i=0;i<=m;i++){            arr[i][0]=0;        }        for(j=0;j<=n;j++){            arr[0][j]=0;        }        for(i=1;i<=m;i++){            for(j=1;j<=n;j++){                if(ch1[i-1]==ch2[j-1]){                    arr[i][j]=arr[i-1][j-1]+1;                }else{                    arr[i][j]=Math.max(arr[i-1][j], arr[i][j-1]);                }            }        }        System.out.println(arr[m][n]);          }}
0 0
原创粉丝点击