动态规划练习题
1.给出不同面额的硬币以及一个总金额. 写一个方法来计算给出的总金额可以换取的最少的硬币数量. 如果已有硬币的任意组合均无法与总金额面额相等, 那么返回 -1。
public static int dp(int[] arr, int count) {
int[] cost = new int[count + 1];
int n = arr.length;
//初始条件为0,即0块钱需要0枚硬币
cost[0] = 0;
for (int i = 1; i <= count; i++) {
//先将cost的值设为无穷大,意为该额度无法凑硬币
cost[i] = Integer.MAX_VALUE;
//遍历硬币的额度
for (int j = 0; j < n; j++) {
//将问题化为子问题
//如果下标不为负数并且该额度可以凑硬币则执行语句
if (i - arr[j] >= 0 && cost[i - arr[j]] != Integer.MAX_VALUE) {
//设最后一枚硬币为cost[i],即最少枚数为cost[i-arr[j]]加上最后一枚硬币或者不加最后一枚硬币
cost[i] = Math.min(cost[i], cost[i - arr[j]] + 1);
}
}
}
//如果不能凑成额度,则返回-1
if (cost[count] == Integer.MAX_VALUE) {
return -1;
}
return cost[count];
}
2.有一个机器人的位于一个 m × n 个网格左上角。机器人每一时刻只能向下或者向右移动一步。机器人试图达到网格的右下角。问有多少条不同的路径?
public static int dp(int m,int n) {
int[][] num = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
//如果在第一行或者第一列,意味着只能向下或向右走
//所以只有一种方法
if (i == 0 || j == 0) {
num[i][j] = 1;
} else {
//走向最后一列的方法有最后一步是向下走
//或者最后一步向右走
//这两种方法加起来即为走到最后一点的方式
num[i][j] = num[i - 1][j] + num[i][j - 1];
}
}
}
return num[m - 1][n - 1];
}
3.在一个数组arr中,找出一组不相邻的数字,使得最后的和最大。
public static int dp(int[] arr) {
//定义存储最大和的数组
int[] opt = new int[arr.length];
//如果只有一个元素,则该元素就是最大和
opt[0] = arr[0];
//如果只有两个元素,比较两个元素大小
opt[1] = Math.max(arr[0], arr[1]);
for (int i = 2; i < arr.length; i++) {
//此时又分为选当前的数和不选两种情况
//如果选当前的数,则相邻的无法选择
//否则就看前一个数的最优解
opt[i] = Math.max(opt[i - 1], opt[i - 2] + arr[i]);
}
return opt[arr.length - 1];
}
4.给定一个正整数s, 判断一个数组arr中,是否有一组数字加起来等于s。
public static boolean dp(int[] arr, int n) {
boolean[][] dpArray = new boolean[arr.length][n + 1];
for (int i = 0; i < arr.length; i++) {
//当n为0时,代表已经有数拼凑成,所以第一列全部为true
dpArray[i][0] = true;
}
//当下标为0时,除非arr[0]==n,否则全部为false
Arrays.fill(dpArray[0], false);
if (n >= arr[0]) {
//如果n的值大于等于arr[0],则置为true
dpArray[0][arr[0]] = true;
}
for (int i = 1; i < arr.length; i++) {
for (int j = 1; j < n + 1; j++) {
if (arr[i] > j) {
//如果arr[i]的值大于j,则说明不能选该值,此时只有一种情况
dpArray[i][j] = dpArray[i - 1][j];
} else {
//否则就看两种情况之一是否满足
dpArray[i][j] = dpArray[i - 1][j - arr[i]] || dpArray[i - 1][j];
}
}
}
return dpArray[arr.length - 1][n];
}