现存人民币面额 【1, 2, 5, 10】,要找零N元,问最少需要多少张人民币?
N为1,最少需要1张。f(1) = 1
N为2,最少需要1张。f(2) = 1
N为3,最少需要2张。f(3) = 2
N为4,最少需要2张。f(4) = 2
N为5,最少需要1张。f(5) = 1
N为6,最少需要2张。f(6) = 2
N为7,最少需要2张。f(7) = 2
N为8,最少需要3张。f(8) = 3
N为9,最少需要3张。f(9) = 3
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
思路:
当N为2时
1张2元 f(2) = 1 需要1张
当N为3时
1张2元 + 1元最少组合 需要2张: f(2) + f(1) = 2
1张1元 + 2元最少组合 需要2张: f(1) + f(2) = 2
当N为4时
1张2元 + 2元最少组合 需要2张: f(2) + f(3) = 2
1张1元 + 3元最少组合 需要2张: f(1) + f(3) = 3
取最小值2张
当N为5时
1张5元 f(5) = 1 需要1张
.。。。。。。
当N为9时
1张10元 + ? 不满足条件: f(10) + ? ------- 不满足条件
1张5元 + 4元最少组合 需要3张:f(5) + f(4) = 1 + 2 = 3 ------------ 5 + (2 + 2) 4最少2张
1张2元 + 7元最少组合 需要3张:f(2) + f(7) = 1 + 2 = 3 ------------ 2 + (2 + 5) 7最少2张
1张1元 + 8元最少组合 需要4张:f(1) + f(8) = 1 + 3 = 4 ------------ 1 + (1 + 2 + 5) 8最少3张
取最小值3张
public class Application {
public static void main(String[] args) {
int[] table = {1, 2, 5};
System.out.println(split(5, table));
}
static int split(int total, int[] table) {
int[] result = new int[total + 1];
Arrays.fill(result, Integer.MAX_VALUE);
for (int i = 1; i <= total; i++) {
for (int j = table.length - 1; j >= 0; j--) {
if (table[j] > i) { // 找零1,面值5
continue;
}
if (table[j] == i) { // 找零5,面值5. 1张就够了
result[i] = 1;
break;
}
int r = i - table[j]; // 找零9 - 面值5 = 剩余4
int rNum = 1 + result[r]; // 1(面值5一张) + 剩余4的最优解数
result[i] = Math.min(result[i], rNum);
}
}
return result[total];
}
}
--------------------------------------------------------------
找零N元,总共有多少种方法?
public class Application {
public static void main(String[] args) {
int[] table = {1, 2, 5};
System.out.println(total(5, table));
}
/**
* for循环 k=1 k从1开始 。 结果为列之和
* 0元,1元,2元,3元,4元,5元
* 组合中包含1且都小于等于1 [0, 1, 1, 1, 1, 1]
* 组合中包含2且都小于等于2 [0, 0, 1, 1, 2, 2]
* 组合中包含5且都小于等于5 [0, 0, 0, 0, 0, 1]
* ----------------------------------------
* for循环 k=0 k从0开始。 结果为列最后一个(已求和)。
* 0元,1元,2元,3元,4元,5元
* 组合中面值小于等于1 [0, 1, 1, 1, 1, 1]
* 组合中面值小于等于2 [0, 1, 2, 2, 3, 3]
* 组合中面值小于等于5 [0, 1, 2, 2, 3, 4]
* @param money
* @param table
* @return
*/
static int total(int money, int[] table) {
int[][] dp = new int[table.length][money + 1];
for (int i = 0; i < table.length; i++) { //table[i]为对应的面值
for (int j = 1; j < money + 1; j++) { // j表示找零数
for (int k = 0; k * table[i] <= j; k++) { // 包含k张同种钱币,面值table[i]
if (k * table[i] == j) { // k张同种钱币恰好找零
dp[i][j] += 1;
} else {
if (i > 0) {
// (零钱总数 - k张面值table[i])的组合数,说明:(i-1)表示面值小于table[i]
dp[i][j] += dp[i - 1][j - k * table[i]];
}
}
}
}
}
return dp[table.length - 1][money];
}
}
---------------------------------------------------------------
最长公共子列
public class Application {
public static void main(String[] args) {
String a = "dbabcdfe";
String b = "cabcdc";
System.out.println(lcs(a, b));
}
/**
* a = "dbabcdfe";
* b = "cabcdc";
* a[2] = b[1] dp[2][1] = 1 = 1
* a[3] = b[2] dp[3][2] = dp[2][1] + 1 = 2
* a[4] = b[3] dp[4][6] = dp[3][2] + 1 = 3
* a[5] = b[4] dp[5][4] = dp[3][2] + 1 = 4
*
* [0, 0, 0, 0, 1, 0]
* [0, 0, 1, 0, 0, 0]
* [0, 1, 0, 0, 0, 0]
* [0, 0, 2, 0, 0, 0]
* [1, 0, 0, 3, 0, 1]
* [0, 0, 0, 0, 4, 0]
* [0, 0, 0, 0, 0, 0]
* [0, 0, 0, 0, 0, 0]
* @param a
* @param b
* @return
*/
static String lcs(String a, String b) {
int[][] dp = new int[a.length()][b.length()];
for (int i = 0; i < a.length(); i++) {
for (int j = 0; j < b.length(); j++) {
if (a.charAt(i) == b.charAt(j)) {
if (i > 0 && j > 0) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = 1;
}
}
}
}
int x = 0;
int len = 0;
for (int i = 0; i < dp.length; i++) { // 从表中查找最大值
System.out.println(Arrays.toString(dp[i]));
for (int j = 0; j < dp[i].length; j++) {
if (len < dp[i][j]) {
len = dp[i][j];
x = i;
}
}
}
return a.substring(x + 1 - len, x + 1);
}
}