#华为笔试#9.14笔试第1题
public class Exer1Preview {
/*
题目:有一个人过桥,桥上面有 n 块木板,有些木板是断的,如果
走到了断的木板上,则会损失一条生命值,这个人的初始生命值条数
是 m 条生命。每次可以选择 不跳(从当前位置走到下一块木板),
或跳一格(从当前位置跳过一块木板),
或跳两格(从当前位置跳过两块木板)
要求走到终点时,生命值至少有1条。
求顺利过桥的方案数?
输入:m —— 代表初始生命值条数
n —— 代表桥的长度,即桥上总共有多少块木板
k —— 代表桥上有多少块木板是断裂的
k个整数,分别代表断裂木板的编号,第一块木板的编号是 1
输出:顺利过桥的方案数
*/
public static void main(String[] args) {
// 处理输入
Scanner scanner = new Scanner(System.in);
int mOfLifes = scanner.nextInt();
int nOfBridges = scanner.nextInt();
int kOfBreakages = scanner.nextInt();
// 起点对应的位置是 0 ,终点对应的位置是 nOfBridges + 1
boolean[] sequenceOfBridges = new boolean[nOfBridges + 2];
int sequence = 0; // 代表断裂木板的编号
for(int i = 0;i < kOfBreakages;i++){
sequence = scanner.nextInt();
// 若第 i 块木板断裂,则 sequenceOfBridges[i]为true,否则为false
sequenceOfBridges[sequence] = true;
}
// 中间过程
/*
算法思想:
动态规划,dp[i][j]:从起点走到第i块木板剩余j条命的 走法方案数
初始状态:
dp[0][mOfLifes] = 1, (从起点走到起点,剩余mOfLifes条命的走法只有1种)
dp[0][j] = 0 ,其中j < mOfLifes (从起点走到起点,剩余j条命的走法是0种)
状态转移方程:
dp[i][j+lose] = dp[i-1][j] + dp[i-2][j] + dp[i-3][j]
分析:若第i块木板断裂,则lose的值为-1,若第i块木板未断裂,则lose的值为0
若想求出从起点走到第i块木板有多少种走法,取决于:
从起点走到第i-1块木板的走法,再走一步
从起点走到第i-2块木板的走法,再跳过一格
从起点走到第i-3块木板的走法,再跳过两格
因为第i块木板有可能是断裂的,所以走到第i块时,剩下的生命值是j+lose
*/
int[][] dp = new int[nOfBridges+2][mOfLifes+1];
dp[0][mOfLifes] = 1;
int lose = 0;
for(int i = 1;i <= nOfBridges+1;i++){
lose = sequenceOfBridges[i] ? -1 : 0;
// 走一步
if(i-1 >= 0){
for(int j = 1;j <= mOfLifes;j++){
dp[i][j+lose] = dp[i][j+lose] + dp[i-1][j];
}
}
// 跳一格
if(i-2 >= 0){
for(int j = 1;j <= mOfLifes;j++){
dp[i][j+lose] = dp[i][j+lose] + dp[i-1][j];
}
}
// 跳两格
if(i-3 >= 0){
for(int j = 1;j <= mOfLifes;j++){
dp[i][j+lose] = dp[i][j+lose] + dp[i-1][j];
}
}
}
// 处理输出
int solutions = 0;
for(int i = 1;i < mOfLifes;i++){
solutions = solutions + dp[nOfBridges+1][i];
}
System.out.println(solutions);
}
} #华为笔试#

查看12道真题和解析