1. 程式人生 > >sincerit 跳躍遊戲二(動態規劃問題)

sincerit 跳躍遊戲二(動態規劃問題)

給定一個非負整數陣列,假定你的初始位置為陣列第一個下標。
陣列中的每個元素代表你在那個位置能夠跳躍的最大長度。
你的目標是到達最後一個下標,並且使用最少的跳躍次數。
例如:
A = [2,3,1,1,4]A=[2,3,1,1,4],到達最後一個下標的最少跳躍次數為 22。(先跳躍 11 步,從下標 00 到 11,然後跳躍 33 步,到達最後一個下標。一共兩次)
輸入格式
第一行輸入一個正整數 n(1 \le n \le 100)n(1≤n≤100) ,接下來的一行,輸入 nn 個整數,表示陣列 AA。
輸出格式
最後輸出最少的跳躍次數。
樣例輸入 複製
5
3 1 1 1 1
樣例輸出 複製
2

一直在想那個轉移方程怎麼寫
d[i]表示到達下標為i的最小步數
到達i肯定是由前面的某個下標j然後加上一段距離到達的i, 這個距離可以是1~num[j]
所以就考慮dp[i+j] = min(dp[i]+1,dp[i+j]); 1 <= j <= num[j] ; 後面的dp[i+j]是另一種方法到達的(i+j)的最小步數,因此要先初始化dp為無窮大 , dp[1]=0開始本身就站在1這裡。
所以這些求最大值最小值的這些問題都是min(a, b), max(a,b)這樣的形式
而那些求種類數的動態規劃,都是加法的比如:dp[i] = dp[i-coin[j]] + dp[i]這樣的

#include <stdio.h>
#include <cstring>
#define INF 0x7f7f7f
int dp[105];
// dp[i]表示到下標為i時的最少步數 
int min(int a, int b) {
  return a>b?b:a;
}
int num[105];
int main() {
  int n;
  while (~scanf("%d", &n)) {
    memset(dp, INF, sizeof(dp));
    dp[1] = 0;
    for (int i = 1; i <= n; i++
) scanf("%d", &num[i]); for (int i = 1; i <= n; i++) { for (int j = num[i]; j >= 1; j--) { dp[j+i] = min(dp[i]+1,dp[j+i]); } } printf("%d\n", dp[n]); } return 0; }