2道dp题目练手
1.剑指 Offer 60. n个骰子的点数
题目链接:https://leetcode.cn/problems/nge-tou-zi-de-dian-shu-lcof/
思路挺简单的,考虑利用n-1个骰子时的概率推出n个骰子
class Solution {
public double[] dicesProbability(int n) {
double[][] dp = new double[n + 1][6 * n + 1];
for (double[] num:dp) Arrays.fill(num,0.0);
for (int i = 1;i<=6;i++){
dp[1][i] = 1.0/6.0;
}
for (int i = 2;i<=n;i++){
for (int j = i;j<=6*i;j++){
for (int m = 1;m<=6&&j-m>=0;m++){
dp[i][j] += dp[i-1][j-m]/6;
}
}
}
double[] return_num = new double[5*n+1];
for (int i = 0;i< return_num.length;i++){
return_num[return_num.length-1-i] = dp[n][6*n-i];
}
return return_num;
}
}
2.面试题13. 机器人的运动范围
题目链接:https://leetcode.cn/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
这题我是用dp做的,其中我dp了2次,虽然dp1次也能通过,但我认为dp一次的时候情况不全面,这个方格能否进入,不一定只需要判断左和上,有可能通过右边方格来进入,但题解里面有举例说明只需要判断左和上即可
class Solution {
public int movingCount(int m, int n, int k) {
int[][] dp = new int[m][n];
int count = 1;
dp[0][0] = 1;
for (int i = 1;i<m;i++){
if (dp[i-1][0]==1&&check(i,0,k)){
dp[i][0] = 1;
count++;
}else {
dp[i][0] = 0;
}
}
for (int i =1;i<n;i++){
if (dp[0][i-1]==1&&check(0,i,k)){
dp[0][i] = 1;
count++;
}else {
dp[0][i] = 0;
}
}
for (int i = 1;i<m;i++){
for (int j = 1;j<n;j++){
if ((dp[i-1][j]==1||dp[i][j-1]==1) && check(i,j,k)){
count++;
dp[i][j] = 1;
}else {
dp[i][j] = 0;
}
}
}
for (int i = m-2;i>=0;i--){
for (int j = n-2;j>=0;j--){
if (dp[i][j] == 1) continue;
if ((dp[i+1][j]==1||dp[i][j+1]==1) && check(i,j,k)){
count++;
dp[i][j] = 1;
}else {
dp[i][j] = 0;
}
}
}
return count;
}
private boolean check(int i,int j,int k ){
int count = 0;
while(i!=0){
count += i%10;
i = i/10;
}
while (j!=0){
count += j%10;
j = j/10;
}
if (count<=k) return true;
return false;
}
}