zoukankan      html  css  js  c++  java
  • 动态规划

    有数组penny,penny中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。

    给定数组penny及它的大小(小于等于50),同时给定一个整数aim,请返回有多少种方法可以凑成aim。

    测试样例:
    [1,2,4],3,3
    返回:2
    思路:这里dp[i][j]表示用前i种货币得到面值j的方法数。
    import java.util.*;
    
    public class Exchange {
        public int countWays(int[] penny, int n, int aim) {
            // write code here
            int[][] dp = new int[n][aim+1];
        	for(int i = 0;i < n; i++)
        		dp[i][0] = 1;
        	for(int i = 1;i <= aim; i++){
        		if(i%penny[0]==0)
        			dp[0][i] = 1;
        		else
        			dp[0][i] = 0;
        	}
        	for(int i = 1;i < n; i++){
        		for(int j = 1;j <= aim; j++){
        			int count = 0;
        			int k = 0;
        			while(j-k*penny[i]>=0){
        				count += dp[i-1][j-k*penny[i]];
        				k++;
        			}
        			dp[i][j] = count;
        		}
        	}
        	    		
        	return dp[n-1][aim];
        }
    }

    有n级台阶,一个人每次上一级或者两级,问有多少种走完n级台阶的方法。为了防止溢出,请将结果Mod 1000000007

    给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。

    测试样例:
    1
    返回:1
    public class GoUpstairs {
        public int countWays(int n) {
            int f1 = 1;
            int f2 = 2;
            for(int i = 3; i <= n; ++i){
                int temp = (f1 + f2)%1000000007;
                f1 = f2;
                f2 = temp;
            }
            return f2 ;
        }
    }
    

      

    有一个矩阵map,它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。

    给定一个矩阵map及它的行数n和列数m,请返回最小路径和。保证行列数均小于等于100.

    测试样例:
    [[1,2,3],[1,1,1]],2,3
    返回:4
    思路:这个地方dp[i][j]表示从(0,0)到(i,j)的最小路径和。
        public static int getMin(int[][] map, int n, int m) {
            // write code here
        	int[][] dp = new int[n][m];
        	int sum = 0;
        	for(int i = 0;i < m; i++){
        		dp[0][i] = sum+map[0][i];
        		sum = dp[0][i];
        		
        	}
        	
        	sum = 0;
        	for(int i = 0;i < n; i++){
        		dp[i][0] = sum+map[i][0];
        		sum = dp[i][0];
        	}
        	
        	for(int i = 1;i < n; i++)
        		for(int j = 1;j < m; j++)
        			dp[i][j] = Math.min(dp[i-1][j]+map[i][j], dp[i][j-1]+map[i][j]);
        	return dp[n-1][m-1];
        }
    

      

    这是一个经典的LIS(即最长上升子序列)问题,请设计一个尽量优的解法求出序列的最长上升子序列的长度。

    给定一个序列A及它的长度n(长度小于等于500),请返回LIS的长度。

    测试样例:
    [1,4,2,5,3],5
    返回:3
    思路:这个地方dp[i]表示以第i个数字结尾的最长递增子序列长度。
    public static int getLIS(int[] A, int n) {
            // write code here
    		int[] dp = new int[n];
    		dp[0] = 1;
    		for(int i = 1;i < n; i++)
    			dp[i] = 0;
    		int result = 0;
    		for(int i = 1;i < n; i++){
    			int max = 0;
    			for(int j = i-1;j >= 0; j--)
    				if(A[j]<A[i]&&dp[j]>max)
    					max = dp[j];
    				dp[i] = max+1;
    			if(dp[i]>result)
    				result = dp[i];
    		}
    			
    		return result;
        }
    

      

    一个背包有一定的承重cap,有N件物品,每件都有自己的价值,记录在数组v中,也都有自己的重量,记录在数组w中,每件物品只能选择要装入背包还是不装入背包,要求在不超过背包承重的前提下,选出物品的总价值最大。

    给定物品的重量w价值v及物品数n和承重cap。请返回最大总价值。

    测试样例:
    [1,2,3],[1,2,3],3,6
    返回:6
    思路:这个地方dp[i][j]表示前i个物品在容量为j时所能达到的最大价值。
    import java.util.*;
    
    public class Backpack {
        public int maxValue(int[] w, int[] v, int n, int cap) {
            // write code here
                	int m = 0;
        	for(int i = 0;i < n; i++)
        		m += w[i];
        	//System.out.println(m);
        	int[][] dp = new int[n][m+1];
        	for(int i = 0;i < n; i++)
        		dp[i][0] = 0;
        	
        	for(int i = 0;i <= m; i++)
        		if(i>=w[0])
        			dp[0][i] = v[0];
    
        	
        	for(int i = 1;i < n; i++){
        		for(int j = 1;j <= m; j++){
        			if(j-w[i]>=0)
        				dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);
        			else
        				dp[i][j] = dp[i-1][j];
        			//System.out.print(dp[i][j]+" ");
        		}
        		//System.out.println();
        	}
        		
        	if(cap>m)
        		return dp[n-1][m];
        	else
        		return dp[n-1][cap];
        }
    }
    

      

    对于两个字符串A和B,我们需要进行插入、删除和修改操作将A串变为B串,定义c0,c1,c2分别为三种操作的代价,请设计一个高效算法,求出将A串变为B串所需要的最少代价。

    给定两个字符串AB,及它们的长度和三种操作代价,请返回将A串变为B串所需要的最小代价。保证两串长度均小于等于300,且三种代价值均小于等于100。

    测试样例:
    "abc",3,"adc",3,5,3,100
    返回:8
    思路:dp[i][j]表示把A[0...i-1]字符串转换为B[0...j-1]的最小代价
    import java.util.*;
    
    public class MinCost {
        public int findMinCost(String A, int n, String B, int m, int c0, int c1, int c2) {
            // write code here
    		int[][] dp = new int[A.length()+1][B.length()+1];
    		for(int i = 0;i <= B.length(); i++)
    			dp[0][i] = i*c0;
    		for(int i = 1;i <= A.length(); i++)
    			dp[i][0] = i*c1;
    		for(int i = 1;i <= A.length(); i++)
    			for(int j = 1;j <= B.length(); j++){
    				int result = dp[i-1][j]+c1;			//删除
    				int result2 = dp[i][j-1]+c0;		     //添加
    				int result3 = 0;
    				if(A.charAt(i-1)!=B.charAt(j-1))         //替换 
    					result3 = dp[i-1][j-1]+c2;
    				else
    					result3 = dp[i-1][j-1];
    				int min = result<result2?result:result2;
    				min = min<result3?min:result3;
    				dp[i][j] = min;
    			}
    //		for(int i = 0;i <= A.length(); i++){
    //			for(int j = 0;j <= B.length(); j++)
    //				System.out.print(dp[i][j]+" ");
    //			System.out.println();
    //		}
    		return dp[A.length()][B.length()];
        }
    }
    

      

    给定两个字符串A和B,返回两个字符串的最长公共子序列的长度。例如,A="1A2C3D4B56”,B="B1D23CA45B6A”,”123456"或者"12C4B6"都是最长公共子序列。

    给定两个字符串AB,同时给定两个串的长度nm,请返回最长公共子序列的长度。保证两串长度均小于等于300。

    测试样例:
    "1A2C3D4B56",10,"B1D23CA45B6A",12
    返回:6
    思路:dp[i][j]代表A[0...i]和B[0...j]的最长子序列长度。
    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];
        	boolean flag = false;
        	for(int i = 0;i < m; i++)
        		if(flag){
        			dp[0][i] = 1;
        		}else if(A.charAt(0)==B.charAt(i)){
        			flag = true;
        			dp[0][i] = 1;
        		}
        	flag = false;
        	for(int j = 0;j < n; j++)
        		if(flag){
        			dp[j][0] = 1;
        		}else if(A.charAt(j)==B.charAt(0)){
        			flag = true;
        			dp[j][0] = 1;
        		}
        	
        	for(int i = 1;i < n; i++)
        		for(int j = 1;j < m; j++){
        			int result = dp[i-1][j];
        			int result2 = dp[i][j-1];
        			int result3 = 0;
        			if(A.charAt(i)==B.charAt(j))
        				result3 = dp[i-1][j-1]+1;
        			int max = result>result2?result:result2;
        			max = max>result3?max:result3;
        			dp[i][j] = max;
        		}
    //    	for(int i = 0;i < n; i++){
    //    		for(int j = 0;j < m; j++)
    //    			System.out.print(dp[i][j]+" ");
    //    		System.out.println();
    //    	}
        	return dp[n-1][m-1];
        }
    }
    

      

  • 相关阅读:
    Unix命令大全
    vs2008 与 IE8出现的兼容性问题
    Java 创建文件、文件夹以及临时文件
    如何修改Wamp中mysql默认空密码
    PAT 乙级真题 1003.数素数
    Tags support in htmlText flash as3
    DelphiXE4 FireMonkey 试玩记录,开发IOS应用 还是移植
    10 Great iphone App Review sites to Promote your Apps!
    HTML tags in textfield
    Delphi XE4 IOS 开发, "No eligible applications were found“
  • 原文地址:https://www.cnblogs.com/lxk2010012997/p/5545026.html
Copyright © 2011-2022 走看看