题目描述
动态规划组成部分一:确定状态
子问题
动态规划组成部分二:转移方程
动态规划组成部分三:初始条件和边界情况
动态规划四:计算顺序
Java代码实现
public boolean canCross(int[] stones) {
int n = stones.length;
boolean[][] f = new boolean[n][n];
f[0][0] = true;
List<Integer> list = Arrays.stream(stones).boxed().collect(Collectors.toList());
int index = -1;
for (int i = 1; i < n; i++)
for (int j = 1; j <= i; j++) {
//这里不需要枚举石头i前的每一步,只需要对那些放有石头的坐标进行计算即可
index = list.indexOf(stones[i] - j);
if (index != -1) {
f[i][j] |= f[index][j - 1] || f[index][j];
if (j + 1 < n)
f[i][j] |= f[index][j + 1];
}
}
for (boolean b : f[n - 1])
if (b)
return b;
return false;
}
优化:动态规划加哈希表
Java代码实现
public boolean canCross(int[] stones) {
int n = stones.length;
int t = 0;
HashMap<Integer, HashSet<Integer>> f = new HashMap<>();
for (int i = 0; i < n; i++)
f.put(stones[i], new HashSet<>());
f.get(stones[0]).add(0);
for (int i = 0; i < n - 1; i++) {
HashSet<Integer> tmp = new HashSet<>(f.get(stones[i]));
for (int k : tmp)
for (int j = -1; j <= 1; j++) {
t = stones[i] + k + j;
if (f.containsKey(t))
f.get(t).add(k + j);
}
}
return !f.get(stones[n - 1]).isEmpty();
}
注意:
这里for循环一定要使用tmp,因为f在for循环里面是会变化的,所以要在for循环之前用tmp记录下来for循环之前的f.get(stones[i])。