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 minj′<idp(i−1,j′,k−1).
There are O(N3) dynamic programming states. The first transition takes O(1) time. The second transition takes O(N) time, but only occurs in O(N2) states. Therefore the overall time complexity is O(N3).
#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'; } }