package com.interview.algorithms.dp;
/**
* Created_By: zouzhile
* Date: 3/27/14
* Time: 6:16 PM
*
* You are planting a flower garden with bulbs to give you joyous flowers throughout the year.
* However, you wish to plant the flowers such that they do not block other flowers while they are visible.
*
* You will be given a int[] height, a int[] bloom, and a int[] wilt. Each type of flower is represented by
* the element at the same index of height, bloom, and wilt. height represents how high each type of flower grows,
* bloom represents the morning that each type of flower springs from the ground, and wilt represents the evening
* that each type of flower shrivels up and dies. Each element in bloom and wilt will be a number between 1 and 365
* inclusive, and wilt[i] will always be greater than bloom[i]. You must plant all of the flowers of the same type
* in a single row for appearance, and you also want to have the tallest flowers as far forward as possible.
* However, if a flower type is taller than another type, and both types can be out of the ground at the same time,
* the shorter flower must be planted in front of the taller flower to prevent blocking. A flower blooms in the morning,
* and wilts in the evening, so even if one flower is blooming on the same day another flower is wilting, one can
* block the other.
*
* You should return a int[] which contains the elements of height in the order you should plant your flowers to
* acheive the above goals. The front of the garden is represented by the first element in your return value,
* and is where you view the garden from. The elements of height will all be unique, so there will always
* be a well-defined ordering.
*
* Sample:
* {5,4,3,2,1}
* {1,1,1,1,1}
* {365,365,365,365,365}
* Returns: { 1, 2, 3, 4, 5 }
*
* {5,4,3,2,1}
* {1,5,10,15,20}
* {4,9,14,19,24}
* Returns: { 5, 4, 3, 2, 1 }
*/
public class C12_7_FlowerGarden {
public int[] getOrdering(int[] height, int[] bloom, int[] wilt) {
int[] optimal = new int[height.length];
int[] optimalBloom = new int[bloom.length];
int[] optimalWilt = new int[wilt.length];
// init state
optimal[0] = height[0];
optimalBloom[0] = bloom[0];
optimalWilt[0] = wilt[0];
// run dynamic programming
for(int i = 1; i < height.length; i ++) {
int currHeight = height[i];
int currBloom = bloom[i];
int currWilt = wilt[i];
int offset = 0; // by default, type i is to be put to 1st row
for(int j = 0; j < i; j ++) {
if(currWilt >= optimalBloom[j] && currWilt <= optimalWilt[j] ||
currBloom >= optimalBloom[j] && currBloom <= optimalWilt[j] ||
currWilt >= optimalWilt[j] && currBloom <= optimalBloom[j]) { // life period overlap
if(currHeight < optimal[j]) { // life overlap, and type i is shorter than type j
offset = j;
break;
} else {
offset = j + 1; // type i overlap with type j, and i is taller than j. Put i after j
}
} else { // not overlap with current
if(currHeight < optimal[j]) {
offset = j + 1; // type i not overlap with j, i is shorter than j, put i after j
}
// else keep offset as is considering offset is smaller than j
}
}
// shift the types after offset
for(int k = i - 1; k >= offset; k -- ) {
optimal[k+1] = optimal[k];
optimalBloom[k+1] = optimalBloom[k];
optimalWilt[k+1] = optimalWilt[k];
}
// update optimal
optimal[offset] = currHeight;
optimalBloom[offset] = currBloom;
optimalWilt[offset] = currWilt;
}
return optimal;
}
}