今天繼續寫一道動態規劃題目
給定一個非負整數數組,假定你的初始位置為數組第一個下標。
數組中的每個元素代表你在那個位置能夠跳躍的最大長度。
你的目標是到達最后一個下標,并且使用最少的跳躍次數。
例如:
A=[2,3,1,1,4],到達最后一個下標的最少跳躍次數為2。(先跳躍1步,從下標0到1,然后跳躍3步,到達最后一個下標。一共兩次)
輸入格式
第一行輸入一個正整數n(1≤n≤100),接下來的一行,輸入n個整數,表示數組A。
輸出格式
最后輸出最少的跳躍次數。
樣例輸入
5
3 1 1 1 1
樣例輸出
2
解析
這道題目一開始我們應該會想到,我們要跳到最后一個位置,就把前面的每個位置遍歷一遍,看看那個位置可以直接跳到最后一個位置,然后比較它們的大小,取最小的+1即可得到答案
可是,這樣的話時間復雜度會很高,大概是n^2
但是我們用動態規劃的思想自底向上的話就會輕松很多
例如題目給的2 3 1 1 4的例子
我們把2 3 1 1 4分別標記為1號位置到5號位置 即求從1號位置跳到5號位置的最少步數
從1號位置開始看,可以跳躍的最大步數是2,那么我們把2號位置和3號位置的最少步數置為1號位置的最少步數0加上1步(此時dp[2]=1 dp[3]=1),因為最多能跳到3號位置,而且之前2,3號位置沒有其他方式可以到達,所以直接賦值。
然后開始遍歷2號位,可以跳躍的最大步數是3,那么我們把3,4,5號位的最少步數置為dp[2]+1,由于dp[3]=1比dp[2]+1要小,所以dp[3]不改變,dp[4]和dp[5]賦值為dp[2]+1
以此類推所有位置只需要遍歷一遍,時間復雜度大大降低,大概為n
代碼
int dp[110]={0};
int main()
{
int n;
dp[1]=0;
int k=0;
int num=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&num);
for(k=1;k<=num&&i+k<=n;k++)
{
if(dp[i+k]==0||dp[i+k]>dp[i]+1)
{
dp[i+k]=dp[i]+1;
}
}
}
printf("%d\n",dp[n]);
return 0;
}