You are given a city which lies on the x-axis. It has n buildings. The first building lies in x = 1 and has height h1, the second building lies on x = 2 and has height h2 and so on. You are a gigantic monster with a sword who wants to destroy the city. You are also a computer scientist at heart so you efficiency is the key, hence you want to destroy the city using minimum number of moves.
You can make one of the two moves :
1. Make a horizontal cut from x = L to x = R, cutting down the heights of the buildings from x = L to X = R by 1.
2. make a vertical cut at x = P, completely destroying the building at x = P thereby making its height zero.**
Note that : for the 1st type of move, every city in the range from L to R must have at least 1 height remaining, i.e. you cannot strike through an empty space.
Print the minimum number of moves needed to destroy the city.
Input
First line contains the number of test cases. For each test case, the first line contains the number of buildings n. Second line contains n integers denoting the heights of the building
Output
For every test case, print the minimum number of moves to destroy the city on a new line.
Notes
1 ≤ n ≤ 1000 0 ≤ hi ≤ 1000
Sample Input 0
2
5
2 2 2 3 3
5
10 2 10 2 10
Sample Output 0
3
5
I cannot figure out the approach to the question. My code does not work for the following input: 1 1 1 2 4 5 7 7 8 9** In my code i reduce the min value from all elements. Then find out the subarray between zeros and then compare the length of subarray(j-i) with the minimum value. if the length is less, then then we need to follow move 2, else move 1. My code:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.Scanner;
public class Main {
static int findmin(int arr[], int i, int j) {
int min = Integer.MAX_VALUE;
for (int k = i; k < j; k++) {
if (min > arr[k]) {
min = arr[k];
}
}
return min;
}
static void subtractmin(int arr[], int i, int j, int min) {
//if both the length of subarray and min are equal, we destroy separately
if (j - i <= min) {
for (int k = i; k < j; k++) {
// if
arr[k] = 0;
}
} else {
//subtract all
for (int k = i; k < j; k++)
// if
{
arr[k] -= min;
}
}
}
public static void main(String[] args) {
//int input[] = {10, 2, 10, 2, 10};// 5
//int input[] = {2, 2, 2, 3, 3};// 5
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- != 0) {
int zeros = 0;
int n = sc.nextInt();
int input[] = new int[n];
int min = Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
input[i] = sc.nextInt();
if (min > input[i]) {
min = input[i];
}
if (input[i] == 0) {
zeros++;
}
}
//subtract minimum element from array
int count = 0;
if (zeros == 0) {
count += min;
subtractmin(input, 0, n, min);
} else {
count += min;
subtractmin(input, 0, n, min);
}
//traverse the array and findsubarrays between 0's
//1) if an element is surrounded by 0's it will be destroyed at once separately
// 2) also if length of subarray<min element, they all need to be destroyed separately
// 3) if min<length of subarray they need to be destroyed at once with count+=min
int i = 0, j = 0;
while (true) {
//move i to the first non zero element
for ( i = 0; i < n; i++) {
if (input[i] != 0) {
break;
}
}
//means whole array is 0;
if (i == n) {
System.out.println(Math.min(count, n - zeros));
break;
}
///start with the first non zero element and fin
for (j = i; j <= n; j++) {
if ( j == n || input[j] == 0) {
// take out min element
int minEle = findmin(input, i, j) ;
//if min lement is greater than subarray size, destroy separately
count += Math.min(minEle, j - i);
//System.out.println("count="+count+"min element="+minEle);
// subtract minimum element
subtractmin(input, i, j, minEle);
}
//if last elemnt is not zero
}
}
}
}
}