This problem can be solved by dynamic programming. Let $dp(i,j,k)$ be the minimum number of changes that must be made to the first $i$ entries so that there are $k$ breakouts among the first $i$ entries, and the last of these $k$ breakouts occurs at index $j$.
Suppose we want to compute $dp(i,j,k)$ for some fixed $i$,$j$, and $k$. Then entry $i$ must be equal to $i-j$; if not, we have to change entry $i$. Now we simply need to count the minimum number of changes that need to be made to the first $i-1$ entries. There are two cases: either $j<i$ or $j=i$.
If $j<i$, then the most recent breakout out of the first $i-1$ days must have been on day $j$. So the quantity we want is $dp(i-1,j,k)$.
If $j=i$, then the most recent breakout out of the first $i-1$ days could have been on any day. So the quantity we want is $\min_{j' < i} dp(i-1, j', k-1)$.
There are $O(N^3)$ dynamic programming states. The first transition takes $O(1)$ time. The second transition takes $O(N)$ time, but only occurs in $O(N^2)$ states. Therefore the overall time complexity is $O(N^3)$.
#include <iostream> #include <algorithm> using namespace std; #define INF 1000 int N; int A[100]; int dp[100][100][101]; //[current index][last breakout][number of breakouts] int main() { cin >> N; for(int i=0;i<N;i++) cin >> A[i]; for(int i=0;i<N;i++) for(int j=0;j<=i;j++) for(int k=0;k<=N;k++) dp[i][j][k] = INF; if(A[0] == 0) dp[0][0][1] = 0; else dp[0][0][1] = 1; for(int i=1;i<N;i++) { for(int j=0;j<=i;j++) for(int k=1;k<=i+1;k++) { if(j < i) dp[i][j][k] = dp[i-1][j][k]; else for(int j1=0;j1<i;j1++) dp[i][j][k] = min(dp[i][j][k], dp[i-1][j1][k-1]); if(A[i] != i-j) dp[i][j][k]++; } } for(int k=1;k<=N;k++) { int low = INF; for(int j=0;j<N;j++) low = min(low, dp[N-1][j][k]); cout << low << '\n'; } }