#include #include #include #include using namespace std; int64_t N; vector A; // 残り区間: [L, R) int64_t solve(int L, int R) { return 0; } int64_t dp[2001][2001][2]; const int64_t INF = numeric_limits::max() / 3; int main() { cin >> N; A.resize(N); for(auto &a: A) cin >> a; int64_t answer = numeric_limits::max(); for(int i = 0; i <= N; i++) { for(int j = 0; j <= N; j++) { for(int k = 0; k < 2; k++) { dp[i][j][k] = INF; } } } // 開始位置を決める for(int i = 0; i < N; i++) { // 左側に移動 int64_t cost = A[i] + 2 * i; for(int j = 0; j < i; j++) { cost = max(cost, A[j] + i - j); } dp[i + 1][N][0] = cost; // 右側に移動 cost = A[i] + (N - i - 1) * 2; for(int j = i + 1; j < N; j++) { cost = max(cost, A[j] + j - i); } dp[0][i][1] = cost; } for(int width = N; width >= 1; width--) { for(int i = 0; i <= N - width; i++) { // [i, i + width) // left -> right int64_t cur = dp[i][i + width][0]; if(cur < INF) { assert(i > 0); // 現在地i - 1 // 単純に一つ移動する dp[i + 1][i + width][0] = min(dp[i + 1][i + width][0], max(cur + 1, A[i])); int64_t arrive = max(A[i + width - 1], cur + width); dp[i][i + width - 1][1] = min(dp[i][i + width - 1][1], arrive); } cur = dp[i][i + width][1]; if(cur < INF) { assert(i + width < N); // 現在地i + width // 単純に一つ移動する dp[i][i + width - 1][1] = min(dp[i][i + width - 1][1], max(cur + 1, A[i + width - 1])); int64_t arrive = max(A[i], cur + width); dp[i + 1][i + width][0] = min(dp[i + 1][i + width][0], arrive); } } } for(int i = 0; i <= N; i++) { for(int k = 0; k < 2; k++) { answer = min(answer, dp[i][i][k]); } } cout << answer << endl; }