一:确定状态
- 研究最优策略的最后一步
- 化为子问题
二:转移方程
- 根据子问题定义直接得到
三:初始条件和边界情况
- 细心,考虑周全
四:计算顺序
- 利用之前的计算结果
动态规划题目特点
-
计数:
有多少种方式走到右下角
有多少种方式选出K个数使得和是SUM -
求最大最小值
从左上角走到右下角路径的最大数字和
最长上升子序列的长度 -
求存在性
取石子游戏,先手是否必胜
能不能选出K个数使得和是SUm
例一
public class Main
{
public static void main(String【】 args) {
int【】 A= {2,5,7};
int M=27;
System.out.println(coinChange(A, M));
}
public static int coinChange(int【】 A,int M) {
//
int【】 f=new int【M+1】;
int n =A.length;
f【0】 = 0;
int i,j;
for(i=1;i<=M;i++) {
f【i】 = Integer.MAX_VALUE;
//
for(j=0;j<n;++j) {
if(i>=A【j】&&f[i-A【j】]!=Integer.MAX_VALUE) {
f【i】=Math.min(f[i-A【j】]+ 1,f【i】);
}
}
}
if(f【M】 == Integer.MAX_VALUE) {
f【M】 = -1;
}
return f【M】;
}
}
例二
public static void main(String[] args) {
int n= 1; int m=3;
System.out.println(uniquePaths(n, m)); }
public static int uniquePaths(int m,int n) {
int[][] f = new int[m][n];
int i,j;
for(i=0;i<m;i++) {
for(i=0;i<m;++i) {
for(j=0;j<n;++j) {
if(i==0||j==0) {
f[i][j]=1;
}
else {
f[i][j]=f[i-1][j]+f[i][j-1];
}
}
}
}
return f[m-1][n-1];
}
例三
public boolean canJump(int[] A) {
int n = A.length;
boolean[] f= new boolean[n];
f[0] = true;
for(int j=1;j<n;++j) {
f[j]=false;
//previous stone i
//last jump is from i to j
for(int i =0;i<j;++i) {
if(f[i]&&i+A[i]>=j) {
f[j]=true;
break;
}
}
}
}