动态规划例题1
/*
* 先来看看生活中经常遇到的事吧——假设您是个土豪,身上带了足够的1、5、11元面值的钞票。现在您的目标是凑出某个金额w=15,需要用到尽量少的钞票。
* */
public class Test {
public static void main(String[] args){
int[] f = new int[105];
int n=15,cost=0;
// i为0,则用0张钞票
f[0] = 0;
for(int i = 1 ;i<=n;i++){
// 每次重置cost,以计算当前最优的选择
cost = 1000000;
if (i - 1 >=0) {
// if判断1是否可以使用当前的面额来凑i面额
// +1表示,使用当前面额时,需要的总面额
cost = Math.min(cost,f[i-1]+1);
}
if (i - 5 >=0) {
// if判断5是否可以使用当前的面额来凑i面额
// +1表示,使用当前面额时,需要的总面额
cost = Math.min(cost,f[i-5]+1);
}
if (i - 11 >=0) {
// if判断11是否可以使用当前的面额来凑i面额
// +1表示,使用当前面额时,需要的总面额
cost = Math.min(cost,f[i-11]+1);
}
// 记录凑出i面额需要的最小钞票数
f[i] = cost;
System.out.println("f["+i+"]="+f[i]);
}
int remain = n;
while(remain > 0){
int flag = -1;
// 判断当前使用5面值,还是1面值的钞票
flag = (remain >= 1 && (remain < 5 || f[remain - 1] < f[remain-5])) ? 1 : 5;
// 判断当前使用flag面值,还是11面值的钞票
flag = !(remain >= flag && (remain < 11 || f[remain - flag] < f[remain - 11])) ? 11 : flag;
// 计算剩下的需要抽出的面值
remain -= flag;
// 输出当前使用的面值
System.out.println(flag);
}
}
}
动态规划例题2
/*
最长上升子序列(LIS)问题:给定长度为n的序列a,从a中抽取出一个子序列,这个子序列需要单调递增。问最长的上升子序列(LIS)的长度。
e.g. 1,5,3,4,6,9,7,8的LIS为1,3,4,6,7,8,长度为6。
*/
import java.lang.reflect.Array;
public class Test02 {
public static void main(String[] args){
// 最坏情况,数列是降序的,最长升序子序列长度为1
int[] f = {1,1,1,1,1,1,1,1};
int[] a = {1,5,3,4,6,9,7,8};
int[] pos = new int[8];
for (int x = 0; x < a.length;x++){
for (int p = 0; p < x ;p++){
if(a[p] < a[x]){
// 计算f[x]结尾的子序列长度时,其之前的以f[p]结尾的子序列长度是已知的
// p是与f[x]求解直接相关的量,x是当前的局面,f(p)是p->x的状态转移方程
f[x] = Math.max(f[p]+1,f[x]);
}
}
}
int ans = -1;
for(int x = 0;x < a.length;x++){
// 目标f(T)
ans = Math.max(ans,f[x]);
}
// 遗留一个问题,如何输出这个子序列
System.out.println(ans);
}
}