Problem p03161 (C++)

Buggy submission (status: Runtime Error):
/* Educational DP Contest 2019/1/6
 * B Frog-2
 * 2020.3.29 練習
 *  Aの変化系．ジャンプ先が最大100から選ぶことになる．
 */
#include <algorithm> // max
#include <iostream>
#include <vector>
// #include<cmath>
using namespace std;

int abs(int x) { return (x >= 0) ? x : -x; }

// 最長増加部分列(LIS)
int n;            // 2~10^5
int k;            // 1~100 ジャンプ先可能数
vector<int> h;    // 数字列 1~10^4
vector<int> cost; // コストのメモ

// 入力
void init() {
  cin >> n;
  cin >> k;
  h.assign(n + 1, 0);
  cost.assign(n + 1, 0);
  for (int i = 1; i < n + 1; i++) {
    cin >> h[i];
  }
  return;
}

/* 再帰関数で実装した場合(Aの場合)
int recur(int k){
  // メモがある場合
  if(cost[k]) return cost[k];  //メモあり
  // 境界条件
  if(k==n) return 0;
  if(k==n-1) return abs(h[n-1]-h[n]);
  // 再帰
  // メモ化
  cost[k] = min( recur(k+1)+abs(h[k]-h[k+1]), recur(k+2)+abs(h[k]-h[k+2]) );
  cout << "mem: k=" << k << ", cost=" << cost[k] << endl;
  return cost[k];
}
//*/

//* DPで実装した場合
void dodp() {
  // 境界条件
  cost[n] = 0;
  int temp;
  // k未満しか飛べない位置
  for (int i = n - 1; i > n - k; i--) {
    // cout << i << " ";
    temp = cost[i + 1] + abs(h[i] - h[i + 1]); // k>=1なので
    for (int j = 2; i + j < n + 1; j++) {
      temp = min(temp, cost[i + j] + abs(h[i] - h[i + j]));
    }
    cost[i] = temp;
    // cout << "db1: i " << i << " cost: " << temp << endl;
  }
  for (int i = n - k; i > 0; i--) {
    temp = cost[i + 1] + abs(h[i] - h[i + 1]); // k>=1なので
    for (int j = 2; j < k + 1; j++) {
      temp = min(temp, cost[i + j] + abs(h[i] - h[i + j]));
    }
    cost[i] = temp;
    // cout << "db2: i " << i << " cost: " << temp << endl;
  }
}
//*/

int main(void) {
  init();
  // cout << "test" << endl;
  dodp();
  cout << cost[1] << endl;
  return 0;
}


Fixed submission:
/* Educational DP Contest 2019/1/6
 * B Frog-2
 * 2020.3.29 練習
 *  Aの変化系．ジャンプ先が最大100から選ぶことになる．
 */
#include <algorithm> // max
#include <iostream>
#include <vector>
// #include<cmath>
using namespace std;

int abs(int x) { return (x >= 0) ? x : -x; }

// 最長増加部分列(LIS)
int n;            // 2~10^5
int k;            // 1~100 ジャンプ先可能数
vector<int> h;    // 数字列 1~10^4
vector<int> cost; // コストのメモ

// 入力
void init() {
  cin >> n;
  cin >> k;
  h.assign(n + 1, 0);
  cost.assign(n + 1, 0);
  for (int i = 1; i < n + 1; i++) {
    cin >> h[i];
  }
  return;
}

/* 再帰関数で実装した場合(Aの場合)
int recur(int k){
  // メモがある場合
  if(cost[k]) return cost[k];  //メモあり
  // 境界条件
  if(k==n) return 0;
  if(k==n-1) return abs(h[n-1]-h[n]);
  // 再帰
  // メモ化
  cost[k] = min( recur(k+1)+abs(h[k]-h[k+1]), recur(k+2)+abs(h[k]-h[k+2]) );
  cout << "mem: k=" << k << ", cost=" << cost[k] << endl;
  return cost[k];
}
//*/

//* DPで実装した場合
void dodp() {
  // 境界条件
  cost[n] = 0;
  int temp;
  // k未満しか飛べない位置
  for (int i = n - 1; i > n - k; i--) {
    // cout << i << " ";
    temp = cost[i + 1] + abs(h[i] - h[i + 1]); // k>=1なので
    for (int j = 2; i + j < n + 1; j++) {
      temp = min(temp, cost[i + j] + abs(h[i] - h[i + j]));
    }
    cost[i] = temp;
    if (i == 1) {
      break;
    }
    // cout << "db1: i " << i << " cost: " << temp << endl;
  }
  for (int i = n - k; i > 0; i--) {
    temp = cost[i + 1] + abs(h[i] - h[i + 1]); // k>=1なので
    for (int j = 2; j < k + 1; j++) {
      temp = min(temp, cost[i + j] + abs(h[i] - h[i + j]));
    }
    cost[i] = temp;
    // cout << "db2: i " << i << " cost: " << temp << endl;
  }
}
//*/

int main(void) {
  init();
  // cout << "test" << endl;
  dodp();
  cout << cost[1] << endl;
  return 0;
}