I'm reading this excellent tutorial by Dumitru on DP based problems here. And I'm trying to come up with a DP based approach for the FlowerGarden problem mentioned in the list of 1D DP problems.
I can only think of a non-DP solution that would involve initially sorting the flowers in an order and then reordering them based on different condition checks mentioned in the problem. That doesn't classify as DP, does it?
The editorial also doesn't mention anything about DP.
Could anyone, by any chance, point me to a proper DP-based solution to this problem?
Thanks!
Edit:
I didn't realize the link would require registration. This is the problem:
Problem Statement
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.
Edit two:
Example 1:
height={5,4,3,2,1}
bloom={1,1,1,1,1}
wilt={365,365,365,365,365}
Returns: { 1, 2, 3, 4, 5 }
These flowers all bloom on January 1st and wilt on December 31st. Since they all may block each other, you must order them from shortest to tallest.
Example 2:
h={5,4,3,2,1}
b={1,5,10,15,20}
w={4,9,14,19,24}
Returns: { 5, 4, 3, 2, 1 }
The same set of flowers now bloom all at separate times. Since they will never block each other, you can order them from tallest to shortest to get the tallest ones as far forward as possible.
Example 3:
height={5,4,3,2,1}
bloom={1,5,10,15,20}
wilt={5,10,14,20,25}
Returns: { 3, 4, 5, 1, 2 }
The difference here is that the third type of flower wilts one day earlier than the blooming of the fourth flower. Therefore, we can put the flowers of height 3 first, then the flowers of height 4, then height 5, and finally the flowers of height 1 and 2. Note that we could have also ordered them with height 1 first, but this does not result in the maximum possible height being first in the garden.
It's not a dynamic programming problem. It's a greedy algorithm problem.
This confused me too, since topcoder's own dynamic programming tutorial links to it as a practice problem in the “Elementary” section.
Sort the flowers by height, shortest to tallest. Start with an empty list of rows. For each flower (shortest to tallest), find the forward-most place where you can insert that flower such that it blocks no flowers behind it.
In Python:
def getOrdering(height, bloom, wilt):
flowers = zip(height, bloom, wilt)
flowers.sort()
def flowersOverlap(f1, f2):
# Overlap if each blooms before the other wilts.
return f2[1] <= f1[2] and f1[1] <= f2[2]
rows = [ ]
for flower in flowers:
rowIndex = len(rows)
# Start at the back and march forward as long as
# `flower` wouldn't block any flowers behind it.
while rowIndex > 0 and not flowersOverlap(flower, rows[rowIndex - 1]):
rowIndex -= 1
rows[rowIndex:rowIndex] = [flower]
return [flower[0] for flower in rows]
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;
}
This is my tested working code.
I'have been struggling with this exact question for a whole day, and also, i couldn't find any DP solution to it.
Here is my greedy approach in java, similar to others already posted, the key point is to proceed under a height ordering. The reason is to avoid dealing with intermediate heights (referring to the already computed), given that a intermediate height can change the relative order of the previously computed ones.
int[] height = new int[]{5, 3, 4};
int[] start = new int[]{1, 3, 1};
int[] end = new int[]{2, 4, 4};
System.out.println(Arrays.toString(new FlowerGarden().getOrdering(height, start, end)));
This is the only optimal substructure I could find. But given that there is no overlapping among subproblems, this algorithm should not be considered DP but greedy.
private static boolean intersects(final int[] starts, final int[] ends, int i1, int i2) {
return !(ends[i1] < starts[i2] || ends[i2] < starts[i1]);
}
public int[] getOrdering(final int[] height, final int[] starts, final int[] ends) {
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
public int compare(Integer i, Integer j) {
return Integer.compare(height[i], height[j]);
}
}
);
for (int i = 0; i < height.length; i++) {
minHeap.add(i);
}
LinkedList<Integer> list = new LinkedList<Integer>();
while (minHeap.size() > 0) {
Integer index = minHeap.poll();
int p = 1;
int pos = 0;
for (Integer i : list) {
if (intersects(starts, ends, i, index)) {
pos = p;
}
p++;
}
list.add(pos, index);
}
int[] ret = new int[height.length];
int j = 0;
for (Integer i : list) {
ret[j++] = height[i];
}
return ret;
}
BTW, the DP solutions I have seen posted here fail for this example.
Cheers
I tried to solve this problem too. The main idea of my approach is to build a tree where each child is overlaped at least once by its parent.
For example, if we have three flower types of heigths 4,2 and 1 growing and dying on the same days, then, the resulting tree should be:
On the other hand, if 4 and 2 and 4 and 1 live at the same time but 2 and 1 do not coexist then, the resulting tree should be:
That will generate a tree which is consistent with the problem contraints. Nonetheless the problem statement also includes a cost function making some solutions better than others.
...you also want to have the flowers in rows which are more towards the front be as tall as possible.
The way to project this preference into our tree is to order all "brothers" (all nodes sharing the same parent) from higher to lower. So 2 comes first than 1.
I built this tree using the following code:
#define INT_MOD(a,b) ((a<0)?(b+(a%b)):(a%b))
#define DIST(a,b) ((a-b>=0)?(a-b):(b-a))
//Prev: ForAll(i), bloom[i] < wilt[i]
inline bool isOverlap(vector<int> & bloom,
vector<int> & wilt,
vector<int> & height,
unsigned int idxPrev, unsigned int idxFollowing)
{
int f1A = bloom[idxPrev];
int f1B = wilt[idxPrev];
int f2A = bloom[idxFollowing];
int f2B = wilt[idxFollowing];
bool notIntersecting =
f2A > f1B /* --[--]-(--)-- */ ||
f1A > f2B /* --(--)-[--]-- */ ;
return height[idxPrev] > height[idxFollowing] && !notIntersecting;
}
class CPreference {
public:
static vector<int> * pHeight;
static bool preference(int a, int b)
{
return (*pHeight)[a] > (*pHeight)[b];
}
};
vector<int> * CPreference::pHeight = NULL;
vector<int> getOrdering(vector<int> height,
vector<int> bloom,
vector<int> wilt)
{
int l = height.size();
vector<int> state = vector<int>(l, -1); /* Tree where each leave points to its
parent. Being that parent the first
flower type that is forced to be
after (backwards) its children */
//This loop is the dynamic programming core.
for(int i = 0; i < l; i++)
for(int j = INT_MOD((i-1),l); j != i; j = INT_MOD((j-1),l))
{
if(isOverlap(bloom, wilt, height, i, j) &&
(state[j] < 0 || DIST(height[j],height[i]) < DIST(height[j], height[state[j]])))
{
state[j] = i;
}
}
vector<vector<int> > groups; //Groups of indexes overlapped by the element at the same index
for(int i = 0; i < l+1; i++)
groups.push_back(vector<int>()); // (l+1) for no overlapped indexes group.
for(int i = 0; i < l; i++)
{
int k = state[i];
if(k < 0) k = l;
groups[k].push_back(i);
}
CPreference::pHeight = &height;
for(vector<vector<int> >::iterator it = groups.begin(); it != groups.end(); it++)
sort(it->begin(),it->end(), CPreference::preference);
At this point, Each row (i) of groups contains, ordered from higher to lower, all flower types indexes that should be placed before the flower type of index i.
One last step is needed, to flatten groups into an output vector. That is, to build a vector where each element is followed by either:
Its parent on the tree.
It next brother when sorted by height.
That can be done by a depth visit of each node of group. I think that is the weak point of my solution. I had not so much time so I just made a naive recursive implementation:
//PRE: each vector, v, in 'groups' is sorted using CPreference
void flattenTree(vector<vector<int> > & groups, vector<int> & out, int currentIdx /*parent*/, int l)
{
int pIdx = currentIdx;
if(pIdx < 0) pIdx = l;
vector<int> & elements = groups[pIdx];
vector<int> ret;
for(vector<int>::iterator it = elements.begin(); it != elements.end(); it++)
{
flattenTree(groups, out ,*it, l);
}
if(currentIdx>=0)
out.push_back(currentIdx);
}
Which is used to completed getOrdering function:
vector<int> getOrdering(vector<int> height,
vector<int> bloom,
vector<int> wilt)
{
int l = height.size();
vector<int> state = vector<int>(l, -1); /* Tree where each leave points to its
parent. Being that parent the first
flower type that is forced to be
after (backwards) its children */
for(int i = 0; i < l; i++)
for(int j = INT_MOD((i-1),l); j != i; j = INT_MOD((j-1),l))
{
if(isOverlap(bloom, wilt, height, i, j) &&
(state[j] < 0 || DIST(height[j],height[i]) < DIST(height[j], height[state[j]])))
{
state[j] = i;
}
}
vector<vector<int> > groups; //Groups of indexes overlapped by the element at the same index
for(int i = 0; i < l+1; i++)
groups.push_back(vector<int>()); // (l+1) for no overlapped indexes group.
for(int i = 0; i < l; i++)
{
int k = state[i];
if(k < 0) k = l;
groups[k].push_back(i);
}
CPreference::pHeight = &height;
for(vector<vector<int> >::iterator it = groups.begin();
it != groups.end(); it++)
sort(it->begin(),it->end(), CPreference::preference);
vector<int> ret;
flattenTree(groups, ret, -1, l);
for(unsigned int i = 0; i < ret.size(); i++)
ret[i] = height[ret[i]];
return ret;
}
Please, let my know if you found a better solution or if know any way to improve mine.
package topcoders;
import java.util.ArrayList;
import java.util.List;
public class FlowerGarden {
public int[] getOrdering(int[] height, int[] bloom, int[] wilt) {
int[] order = new int[height.length];
List<Integer> heightList = new ArrayList<Integer>();
for (int i = 0; i < height.length; i++) {
heightList.add(height[i]);
}
heightList = quickSort(heightList);
for (int i = 0; i < height.length; i++) {
height[i] = heightList.get(i);
}
order = height;
for (int i = 0; i < order.length; i++) {
int j = 0;
while (j < order.length - 1
&& isBlocking(j + 1, j, order, bloom, wilt)) {
int placeHolder = order[j];
order[j] = order[j + 1];
order[j + 1] = placeHolder;
j++;
}
}
return order;
}
public boolean isBlocking(int isBlocked, int isBlocking, int[] order,
int[] bloom, int[] wilt) {
if (order[isBlocking] > order[isBlocked]
&& bloom[isBlocked] <= wilt[isBlocking]
&& wilt[isBlocked] >= bloom[isBlocking]) {
return true;
} else {
return false;
}
}
public List<Integer> quickSort(List<Integer> array) {
if (array.size() <= 1) {
return array;
}
int pivotIndex = array.size() / 2;
int pivot = array.get(pivotIndex);
List<Integer> less = new ArrayList<Integer>();
List<Integer> greater = new ArrayList<Integer>();
int l = 0;
int g = 0;
for (int i = 0; i < array.size(); i++) {
if (i == pivotIndex) {
continue;
} else if (array.get(i) >= pivot) {
less.add(array.get(i));
} else {
greater.add(array.get(i));
}
}
List<Integer> lessResult = quickSort(less);
List<Integer> greaterResult = quickSort(greater);
List<Integer> result = new ArrayList<Integer>();
result.addAll(lessResult);
result.add(pivot);
result.addAll(greaterResult);
return result;
}
public static void main(String[] args) {
int[] height = { 5, 4, 3, 2, 1 };
int[] bloom = { 1, 5, 10, 15, 20 };
int[] wilt = { 5, 10, 14, 20, 25 };
FlowerGarden g = new FlowerGarden();
List<Integer> arrayList = new ArrayList<Integer>();
int[] array = g.getOrdering(height, bloom, wilt);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
A toplogical sort approach:
#include<stdio.h>
#include<stdlib.h>
#include <vector>
#include <queue>
using namespace std;
#define MAX_FLOWERS 50
struct flower
{
int id;
int height;
int bloom;
int wilt;
bool visited;
int ind;
};
struct flower_comp
{
bool operator()(const struct flower* lhs, const struct flower* rhs) const
{
return rhs->height > lhs->height;
}
};
inline bool overlap(const struct flower& a, const struct flower& b)
{
return !((a.bloom < b.bloom && a.wilt < b.bloom) || (a.bloom > b.bloom && a.bloom > b.wilt));
}
void getOrdering(int height[], int bloom[], int wilt[], int size)
{
struct flower flowers[MAX_FLOWERS];
for(int i = 0; i < size; i++)
{
flowers[i].id = i;
flowers[i].height = height[i];
flowers[i].bloom = bloom[i];
flowers[i].wilt = wilt[i];
flowers[i].visited = false;
flowers[i].ind = 0;
}
bool partial_order[MAX_FLOWERS][MAX_FLOWERS] = {false};
for(int i = 0; i < size; i++)
{
for(int j = i + 1; j < size; j++)
{
if(overlap(flowers[i], flowers[j]))
{
if(flowers[i].height < flowers[j].height)
{
partial_order[i][j] = true;
flowers[j].ind++;
}
else
{
partial_order[j][i] = true;
flowers[i].ind++;
}
}
}
}
priority_queue<struct flower*, vector<struct flower*>, flower_comp> pq;
for(int i = 0; i < size; i++)
{
if(flowers[i].ind == 0)
{
pq.push(&flowers[i]);
}
}
printf("{");
bool first = true;
while(!pq.empty())
{
struct flower* tmp = pq.top();
pq.pop();
tmp->visited = true;
if(!first)
{
printf(",");
}
first = false;
printf("%d", tmp->height);
for(int j = 0; j < size; j++)
{
if(!flowers[j].visited && partial_order[tmp->id][j])
{
flowers[j].ind--;
if(flowers[j].ind == 0)
{
pq.push(&flowers[j]);
}
}
}
}
printf("}\n");
}
int main(int argc, char** argv)
{
int height[] = {5,4,3,2,1};
int bloom[] = {1,1,1,1,1};
int wilt[] = {365,365,365,365,365};
getOrdering(height, bloom, wilt, sizeof(height)/sizeof(height[0]));
int height0[] = {5,4,3,2,1};
int bloom0[] = {1,5,10,15,20};
int wilt0[] = {4,9,14,19,24};
getOrdering(height0, bloom0, wilt0, sizeof(height0)/sizeof(height0[0]));
int height1[] = {5,4,3,2,1};
int bloom1[] = {1,5,10,15,20};
int wilt1[] = {5,10,15,20,25};
getOrdering(height1, bloom1, wilt1, sizeof(height1)/sizeof(height1[0]));
int height2[] = {5,4,3,2,1};
int bloom2[] = {1,5,10,15,20};
int wilt2[] = {5,10,14,20,25};
getOrdering(height2, bloom2, wilt2, sizeof(height2)/sizeof(height2[0]));
int height3[] = {1,2,3,4,5,6};
int bloom3[] = {1,3,1,3,1,3};
int wilt3[] = {2,4,2,4,2,4};
getOrdering(height3, bloom3, wilt3, sizeof(height3)/sizeof(height3[0]));
int height4[] = {3,2,5,4};
int bloom4[] = {1,2,11,10};
int wilt4[] = {4,3,12,13};
getOrdering(height4, bloom4, wilt4, sizeof(height4)/sizeof(height4[0]));
}
Same thing as Rob's but in Javascript (ES6):
function getOrdering(height, bloom, wilt) {
var n = height.length;
var idx = [];
for (var i = 0; i < n; ++i) idx[i] = i;
idx.sort( (a, b) => height[a] - height[b] );
var intersect = (a, b) => !(bloom[a] > wilt[b] || bloom[b] > wilt[a]);
for (var i = 1; i < n; ++i) {
// assume they are ordered correctly till index (i-1),
// start moving flower i to the left until it can't move because of intersection
var j = i, flw = idx[i];
while (j > 0 && !intersect(idx[j-1], flw)) {
idx[j] = idx[j-1];
idx[--j] = flw;
}
}
return idx.map( x => height[x] );
}
Similar to Rob, again in Python and slightly convoluted overlapping bloom/wilt check.
H = 0
B = 1
W = 2
def getOrdering(heights, blooms, wilts):
def _f1_after_f2(f1, f2):
fs1 = set(range(f1[B], f1[W]+1))
fs2 = set(range(f2[B], f2[W]+1))
return f1[H] > f2[H] if fs2.intersection(fs1) != set([]) else False
fs = zip(heights, blooms, wilts)
fs.sort()
ffs = []
for f1 in fs:
insert_at = len(ffs)
for f2 in reversed(ffs):
if _f1_after_f2(f1, f2): break
insert_at -= 1
ffs.insert(insert_at, f1)
return [f[H] for f in ffs]
A graph algorithm to solve the problem:
Create a directed graph(V,E):
V -> flower types
E -> relations between 2 flower types
For all pairs (v_i, v_j)
If v_i is smaller than v_j and v_j 'blocks' v_i
draw an edge starting from v_i to v_j
For all nodes v_i
Find the v_i with no incoming edges and the biggest height
-> write it at the end of the result list
-> remove v_i and all of its outgoing edges from graph
For more description checkout this forum:
Topcoder Forum - FlowerGarden
Mine is like insertion sort. For each new flower, it goes from back to front and checks to see if the one in front of it blocks it; if it does, it means it must be placed behind it. Likewise, it also searches from front to back and checks to see if the one behind it blocks it; if it does, it means it must be placed in front of it. If there are no blocks, it simply checks for the best spot height-wise.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#define uint32 uint32_t
static void
Swap(int *AIdx, int *BIdx)
{
int Tmp = *AIdx;
*AIdx = *BIdx;
*BIdx = Tmp;
}
static void
SwapTo(int Start, int End, int *Array)
{
while(Start != End)
{
Swap(&Array[Start], &Array[Start - 1]);
--Start;
}
}
static void
PrintTo(int End, int *Array)
{
for(int Idx = 0;
Idx < End;
++Idx)
{
printf("%d, ", Array[Idx]);
}
printf("\n");
}
/* Does A block B? */
static bool
Blocks(int AIdx, int BIdx, int *Heights, int *Blooms, int *Wilts)
{
bool Result = (Heights[AIdx] > Heights[BIdx] &&
Wilts[AIdx] >= Blooms[BIdx] &&
Blooms[AIdx] <= Wilts[BIdx]);
return Result;
}
static void
Order(int *Heights, int *Blooms, int *Wilts,
int FlowerCount)
{
for(int FlowerIdx = 1;
FlowerIdx < FlowerCount;
++FlowerIdx)
{
PrintTo(FlowerIdx, Heights);
/* front to back */
int MinIdx = -1;
for(int Idx = 0;
Idx < FlowerIdx;
++Idx)
{
if(Blocks(Idx, FlowerIdx, Heights, Blooms, Wilts))
{
MinIdx = Idx;
break;
}
}
/* back to front */
int MaxIdx = -1;
for(int Idx = (FlowerIdx - 1);
Idx >= 0;
--Idx)
{
if(Blocks(FlowerIdx, Idx, Heights, Blooms, Wilts))
{
MaxIdx = (Idx + 1);
break;
}
}
/* best height index */
int BestHeightIdx = -1;
if(MinIdx == -1 &&
MaxIdx == -1)
{
for(int Idx = 0;
Idx < FlowerIdx;
++Idx)
{
if(Heights[FlowerIdx] > Heights[Idx])
{
BestHeightIdx = Idx;
break;
}
}
if(BestHeightIdx == -1)
{
BestHeightIdx = FlowerIdx;
}
}
int SwapToIdx = -1;
if((MaxIdx == -1 && MinIdx != -1) ||
(MinIdx == -1 && MaxIdx != -1) ||
(MaxIdx != -1 && MinIdx != -1 && MaxIdx == MinIdx))
{
SwapToIdx = (MinIdx != -1) ? MinIdx : MaxIdx;
}
else if(BestHeightIdx != -1)
{
SwapToIdx = BestHeightIdx;
}
else
{
fprintf(stderr, "Spot-finding error:\n MinIdx: %d, MaxIdx: %d, BestHIdx: %d\n",
MinIdx, MaxIdx, BestHeightIdx);
exit(1);
}
SwapTo(FlowerIdx, SwapToIdx, Heights);
SwapTo(FlowerIdx, SwapToIdx, Blooms);
SwapTo(FlowerIdx, SwapToIdx, Wilts);
}
}
int
main(int argc, char *argv[])
{
int Heights0[] = {5,4,3,2,1};
int Blooms0[] = {1,1,1,1,1};
int Wilts0[] = {365,365,365,365,365};
int Heights1[] = {5,4,3,2,1};
int Blooms1[] = {1,5,10,15,20};
int Wilts1[] = {4,9,14,19,24};
int Heights2[] = {5,4,3,2,1};
int Blooms2[] = {1,5,10,15,20};
int Wilts2[] = {5,10,15,20,25};
int Heights3[] = {5,4,3,2,1};
int Blooms3[] = {1,5,10,15,20};
int Wilts3[] = {5,10,14,20,25};
int Heights4[] = {1,2,3,4,5,6};
int Blooms4[] = {1,3,1,3,1,3};
int Wilts4[] = {2,4,2,4,2,4};
int Heights5[] = {3,2,5,4};
int Blooms5[] = {1,2,11,10};
int Wilts5[] = {4,3,12,13};
int *AllHeights[] = {Heights0, Heights1, Heights2, Heights3, Heights4, Heights5};
int *AllBlooms[] = {Blooms0, Blooms1, Blooms2, Blooms3, Blooms4, Blooms5};
int *AllWilts[] = {Wilts0, Wilts1, Wilts2, Wilts3, Wilts4, Wilts5};
int AllFlowerCounts[] = {5, 5, 5, 5, 6, 4};
printf("\n");
for(int Idx = 0;
Idx < 6;
++Idx)
{
int *Heights = AllHeights[Idx];
int *Blooms = AllBlooms[Idx];
int *Wilts = AllWilts[Idx];
int FlowerCount = AllFlowerCounts[Idx];
printf("Test %d\n", Idx);
Order(Heights, Blooms, Wilts, FlowerCount);
printf("{ ");
for(int Idx = 0;
Idx < FlowerCount;
++Idx)
{
printf("%d", Heights[Idx]);
if(Idx != (FlowerCount - 1))
{
printf(", ");
}
}
printf(" }\n\n");
}
}
EDIT: This solution is god awful and I came up with a better one that's actually DP; it's as follows: for each flower, loop through all other flowers checking which ones it blocks; for those flowers it blocks, check for all the flowers it blocks, and so on until you get to a flower that doesn't block any other ones. Put that flower in a new array. Backtrack and put each flower before it in the next slot of that new array. If done for each flower, you will get an array full of flowers that don't block any others. You then put each flower as far forward as possible. The DP part of this solution is that sometimes you'll come across the same flower that has already been blocked by another flower previously and has already been put in the new array, so we skip that flower instead of chasing down the flowers it blocks.
I have got the implementation in c++. I have used a vector datatype to store the height, bloom and wilt respectively and then i sorted it w.r.t to height after which i took the flowers one by one and arranged them according to the values associated with them.
here is the code :-
#include<iostream>
#include<vector>
#include<utility>
#include<algorithm>
using namespace std;
bool comp(pair<int, pair<int,int> >& a,pair<int, pair<int,int> >& b ){
return (a.first > b.first);
}
bool justify(pair<int, pair<int,int> >& a,pair<int, pair<int,int> >& b, int k , int
j, vector<pair<int,pair<int,int> > >& v){
if(((b.second.first <= a.second.first) && (b.second.second>= a.second.first)) ||
((b.second.first <= a.second.second) && (b.second.second>= a.second.second)) ||
((b.second.first > a.second.first) && (b.second.second < a.second.second) )){
pair<int, pair<int,int> > temp = v[j];
int i = j-1;
while(i >= k){
v[i+1] = v[i];
i--;
}
v[k] = temp;
return true;
}
return false;
}
int main() {
vector<pair<int,pair<int,int> > > v;
int n,a,b,c;
cin>>n;
for(int i = 0;i < n;i++){
cin>>a>>b>>c;
v.push_back(make_pair(a,make_pair(b,c)));
}
sort(v.begin(), v.end(), comp);
for(int j = 1;j < n;j++){
for(int k = 0;k < j;k++){
bool res = justify(v[k],v[j], k, j, v);
if(res)
break;
}
}
cout<<"output"<<endl;
for(int i = 0;i < n;i++){
cout<<v[i].first<<" "<<v[i].second.first<<" "<<v[i].second.second<<endl;
}
return 0;
}
Related
I am trying to solve subset sum problem with recursive solution, but to make to make it a bit more efficient I am trying to put memoization in it. However the code without memoization gives correct solution but with memoization it doesn't work properly.
public int subsetSum(int num[], int idx, int expecedSum, int dp[]) {
if (expecedSum == 0) {
return 1;
}
else if (idx < 0 || expecedSum < 0) {
return 0;
}
else {
if (dp[expecedSum] == -1) {
int x = subsetSum(num, idx - 1, expecedSum, dp);
int y = subsetSum(num, idx - 1, expecedSum - num[idx], dp);
dp[expecedSum] = (x == 1 || y == 1) ? 1 : 0;
}
return dp[expecedSum];
}
}
public static void main(String args[]) {
Solution s = new Solution();
int num[] = new int[]{1, 2, 3, 4, 5, 6, 7};
int sum = 0;
int n = new Scanner(System.in).nextInt();
int dp[] = new int[n + 1];
for (int i = 0; i < dp.length; i++) {
dp[i] = -1;
}
dp[0] = 1;
s.subsetSum(num, num.length - 1, n, dp);
}
Can someone help me with why this is not working?
If I enter n = 14 then ideally dp[14] should contains 1 but it doesn't contain 1.
The sum is not sufficient to describe the state. The pair (sum, index) is. If you make dp an array of arrays of size (max_sum + 1) x num.length and apply memoization for a pair (idx, expectedSum) in the subsetSet method, it works.
It has been years but this may help someone today.
The idea is to take both the state - means once with including current element into the sum and once excluding current element into the sum. and then taking OR(||) for those values and store in the cache.
the code will look something like this -
#include <iostream>
#include <vector>
using namespace std;
bool sumExists(vector<int> & a, int cursum, int n, vector<vector<int>> &dp) {
if(n==0 && cursum != 0)
return 0;
if(cursum==0)
return 1;
if(dp[n][cursum] != -1) {
return dp[n][cursum];
}
int newsum = cursum - a[n-1];
bool returnval = false;
if(newsum>=0) {
dp[n][newsum] = sumExists(a, newsum, n-1, dp);
dp[n][cursum] = sumExists(a, cursum, n-1, dp);
returnval = dp[n][newsum] || dp[n][cursum];
} else {
dp[n][cursum] = sumExists(a, cursum, n-1, dp);
returnval = dp[n][cursum];
}
return returnval;
}
int main() {
// your code goes here
vector<int> a{2,0,7,8,10};
int n = a.size();
int sum = 11;
vector<vector<int>> dp(n+1, vector<int>(sum+1, -1));
for(int i=0;i<=n;++i) {
dp[i][0]=true;
}
for(int i=1;i<=sum;++i) {
dp[0][i]=false;
}
if(sumExists(a, sum, n, dp)) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}
Find minimum cost of tickets required to buy for traveling on known days of the month (1...30). Three types of tickets are available : 1-day ticket valid for 1 days and costs 2 units, 7-days ticket valid for 7 days and costs 7 units, 30-days ticket valid for 30 days and costs 25 units.
For eg: I want to travel on [1,4,6,7,28,30] days of the month i.e. 1st, 4th, 6th ... day of the month. How to buy tickets so that the cost is minimum.
I tried to use dynamic programming to solve this but the solution is not giving me the correct answer for all cases. Here is my solution in Java :
public class TicketsCost {
public static void main(String args[]){
int[] arr = {1,5,6,9,28,30};
System.out.println(findMinCost(arr));
}
public static int findMinCost(int[] arr) {
int[][] dp = new int[arr.length][3];
int[] tDays = {1,7,30};
int[] tCost = {2,7,25};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < 3; j++) {
if (j==0){
dp[i][j]= (i+1)*tCost[j];
}
else{
int c = arr[i]-tDays[j];
int tempCost = tCost[j];
int k;
if (c>=arr[0] && i>0){
for (k = i-1; k >= 0; k--) {
if (arr[k]<=c){
c = arr[k];
}
}
tempCost += dp[c][j];
int tempCostX = dp[i-1][j] + tCost[0];
tempCost = Math.min(tempCost,tempCostX);
}
dp[i][j] = Math.min(tempCost,dp[i][j-1]);
}
}
}
return dp[arr.length-1][2];
}
}
The solution doesn't work for {1,7,8,9,10} input, it gives 10 but the correct answer should be 9. Also, for {1,7,8,9,10,15} it give 13 but the correct is 11.
I have posted my solution not for other to debug it for me but just for reference. I was taken a bottom-up dynamic programming approach for this problem. Is this approach correct?
Let MC(d) denote the minimum cost that will pay for all trips on days 1 through d. The desired answer is then MC(30).
To calculate MC(d), observe the following:
If there's no trip on day d, then MC(d) = MC(d − 1).
As a special case, MC(d) = 0 for all d ≤ 0.
Otherwise, the minimum cost involves one of the following:
A 1-day pass on day d. In this case, MC(d) = MC(d − 1) + 2.
A 7-day pass ending on or after day d. In this case, MC(d) = min(MC(d − 7), MC(d − 6), …, MC(d − 1)) + 7.
And since MC is nondecreasing (adding a day never reduces the minimum cost), this can be simplified to MC(d) = MC(d − 7) + 7. (Hat-tip to Ravi for pointing this out.)
A 30-day pass covering the whole period. In this case, MC(d) = 25.
As you've realized, dynamic programming (bottom-up recursion) is well-suited to this.
For ease of coding, I suggest we start by converting the list of days into a lookup table for "is this a trip day?":
boolean[] isDayWithTrip = new boolean[31]; // note: initializes to false
for (final int dayWithTrip : arr) {
isDayWithTrip[dayWithTrip] = true;
}
We can then create an array to track the minimum costs, and populate it starting from index 0:
int[] minCostUpThroughDay = new int[31];
minCostUpThroughDay[0] = 0; // technically redundant
for (int d = 1; d <= 30; ++d) {
if (! isDayWithTrip[d]) {
minCostUpThroughDay[d] = minCostUpThroughDay[d-1];
continue;
}
int minCost;
// Possibility #1: one-day pass on day d:
minCost = minCostUpThroughDay[d-1] + 2;
// Possibility #2: seven-day pass ending on or after day d:
minCost =
Math.min(minCost, minCostUpThroughDay[Math.max(0, d-7)] + 7);
// Possibility #3: 30-day pass for the whole period:
minCost = Math.min(minCost, 25);
minCostUpThroughDay[d] = minCost;
}
And minCostUpThroughDay[30] is the result.
You can see the above code in action at: https://ideone.com/1Xx1fd.
One recursive solution in Python3.
from typing import List
def solution(A: List[int]) -> int:
if not any(A):
return 0
tickets = {
1: 2,
7: 7,
30: 25,
}
import sys
min_cost = sys.maxsize
size = len(A)
for length, price in tickets.items():
current_cost = price
idx = 0
last_day = A[idx] + length
while idx < size and A[idx] < last_day:
idx += 1
if current_cost > min_cost:
continue
current_cost += solution(A[idx:])
if current_cost < min_cost:
min_cost = current_cost
return min_cost
if __name__ == '__main__':
cases = {
11: [1, 4, 6, 7, 28, 30],
9: [1, 7, 8, 9, 10],
}
for expect, parameters in cases.items():
status = (expect == solution(parameters))
print("case pass status: %s, detail: %s == solution(%s)" %
(status, expect, parameters))
public class Main03v3
{
public static void main(String[] args)
{
int[] A = {1,7,8,9,10,15,16,17,18,21,25};
System.out.println("Traveling days:\r\n "+Arrays.toString(A));
int cost = solution(A);
System.out.println("\r\nMinimum cost is " + cost);
System.out.println("\r\n" + new String(new char[40]).replace("\0", "-"));
}
public static int solution(int[] A)
{
if (A == null) return -1;
int sevenDays = 7;
int dayCost = 2, weekCost = 7, monthCost = 25;
int ratio_WeekAndDays = weekCost / dayCost;
int len = A.length;
if (len == 0) return -1;
if (len <= 3) return len * dayCost;
int cost[] = new int[len];
int i = 0;
while (i < len)
{
int startIdx = i, endIdx = i + 1;
while (endIdx < len && A[endIdx]-A[startIdx] < sevenDays)
endIdx++;
if (endIdx-startIdx > ratio_WeekAndDays)
{
if (endIdx >= startIdx + sevenDays)
endIdx = startIdx + sevenDays;
int j = startIdx;
cost[j] = ((j == 0) ? 0 : cost[j-1]) + weekCost;
while (++j < endIdx) {
cost[j] = cost[j-1];
}
i = j;
}
else
{
cost[i] = ((i == 0) ? 0 : cost[i-1]) + dayCost;
i++;
}
}
int finalCost = Math.min(cost[len-1], monthCost);
return finalCost;
}
}
Find minimum cost of tickets in JavaScript
case 1 : if input is [1,7,8,9,10] then the required output is 9
case 2 : if input is [1,7,8,9,10,15] then the required output is 11
function calMinCosts(arr){
if(!arr || arr.length===0)
return 0;
var len = arr.length;
var costsOfDateArr = Array.apply(null,{length:arr[len-1]+1}).map(()=>0);
var price1=2,price2=7,price3=25;
var days=7;
var index=0,n=costsOfDateArr.length;
for(var i=1;i<n;i++){
if(i===arr[index]){
if(i>=days+1){
costsOfDateArr[i] = Math.min(costsOfDateArr[i-days-1]+price2, costsOfDateArr[i-1]+price1);
}else{
costsOfDateArr[i] = Math.min(costsOfDateArr[0]+price2, costsOfDateArr[i-1]+price1);
}
index+=1;
}else{
costsOfDateArr[i] = costsOfDateArr[i-1];
}
}
return Math.min(price3,costsOfDateArr[n-1]);
}
console.log(calMinCosts([1,7,8,9,10]))
console.log(calMinCosts([1,7,8,9,10,15]))
Here is the C++ solution including print outs
#include <vector>
#include <iostream>
#include <cmath>
#include <algorithm>
int compute(std::vector<int> &A)
{
int sum[A.size()][A.size()+1];
for (int i = 0; i < A.size(); i++)
{
for(int j =0; j < A.size(); j++)
{
sum[i][j]=2;
}
}
for (int k = 0; k < A.size();k++)
{
sum[k][A.size()]=0;
}
for (int i = 0; i < A.size(); i++)
{
for(int j = 0; j < A.size(); j++)
{
if (i!=j)
{
if (sum[i][i] != 7)
{
int temp = abs(A[j]-A[i]);
if (temp<7 && abs(j-i)>=3)
{
sum[i][i]=7;
sum[i][j]=7;
if (i>j)
{
for(int k = j;k < i;k++)
sum[i][k]=7;
}
else
{
for(int k = i;k < j;k++)
sum[i][k]=7;
}
}
}
}
}
}
for (int i = 0; i < A.size(); ++i)
{
for(int j = 0; j < A.size(); ++j)
{
if (sum[i][j]==7)
{
sum[i][A.size()]+=1;
}
}
}
for (int i = 0; i < A.size(); ++i)
{
for (int j = 0; j < A.size()+1; ++j)
std::cout<<sum[i][j]<<" ";
std::cout<<std::endl;
}
int result = 0;
int row = A.size()-1;
int column = A.size()-1;
while(1)
{
int value = sum[row][A.size()];
if (value == 0)
value=1;
int temp = sum[row][column];
result += temp;
row = row-value;
column = column-value;
while (sum[row][column+1]==7 && row>=0)
{
row-=1;
column-=1;
result+=2;
}
if (row < 0)
break;
}
return result;
}
int solution(std::vector<int> &A) {
if (A.size() > 24)
return 25;
if (A.size() <= 3)
return A.size() * 2;
return std::min(25,compute(A));
}
int main()
{
std::vector<int> AA={1,2,3,4,5,29,30};
std::vector<int> B={1,2,3,4,5};
std::vector<int> A={1,2,3,4,5,9,10,11,12,13,14,17,18,20,21};
std::vector<int> C={1,2,3,12};
std::vector<int> D={1,2,3,4,12,13,14,15,29,30};
std::vector<int> DD={1,2,3,4,5,14,17,18,19,20,23,28,29,30};
std::vector<int> CC={1,2,3,4,5,6,7,9,14,17,18,19,20,23,28,29,30};
std::cout<<solution(AA)<<std::endl;
std::cout<<solution(D)<<std::endl;
std::cout<<solution(B)<<std::endl;
std::cout<<solution(A)<<std::endl;
std::cout<<solution(C)<<std::endl;
std::cout<<solution(DD)<<std::endl;
std::cout<<solution(CC)<<std::endl;
return 0;
}
Solved using the same approach of bottom-up dynamic programming. Here is the full solution :
public class PublicTicketCost {
public static void main(String args[]){
int[] arr = {1,7,8,9,10,15,16,17,18,21,25};
int[] tDays = {1,7,30};
int[] tCost = {2,7,25};
System.out.println(minCost(arr, tDays, tCost));
}
public static int minCost(int[] arr, int[] tDays, int[] tCost) {
int[][] dp = new int[arr.length][tDays.length];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < tDays.length; j++) {
int prevDayIndex = findPrevDayIndex(arr,i,tDays,j);
int prevCost = prevDayIndex>=0 ? dp[prevDayIndex][tDays.length-1] : 0;
int currCost = prevCost + tCost[j];
if(j-1>=0){
currCost = Math.min(currCost, dp[i][j-1]);
}
dp[i][j] = currCost;
}
}
//print(dp);
return dp[arr.length-1][tDays.length-1];
}
private static void print(int arr[][]){
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[0].length; j++) {
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
private static int findPrevDayIndex(int[] arr, int i, int[] days, int j){
int validAfterDate = arr[i] - days[j];
if (validAfterDate<1){
return -1;
}
for (int k = i-1; k >= 0; k--) {
if (arr[k]<=validAfterDate){
return k;
}
}
return -1;
}
}
http://ideone.com/sfgxGo
I have asked a similar question some days ago, but I have yet to find an efficient way of solving my problem.
I'm developing a simple console game, and I have a 2D array like this:
1,0,0,0,1
1,1,0,1,1
0,1,0,0,1
1,1,1,1,0
0,0,0,1,0
I am trying to find all the areas that consist of neighboring 1's (4-way connectivity). So, in this example the 2 areas are as following:
1
1,1
1
1,1,1,1
1
and :
1
1,1
1
The algorithm, that I've been working on, finds all the neighbors of the neighbors of a cell and works perfectly fine on this kind of matrices. However, when I use bigger arrays (like 90*90) the program is very slow and sometimes the huge arrays that are used cause stack overflows.
One guy on my other question told me about connected-component labelling as an efficient solution to my problem.
Can somebody show me any C++ code which uses this algorithm, because I'm kinda confused about how it actually works along with this disjoint-set data structure thing...
Thanks a lot for your help and time.
I'll first give you the code and then explain it a bit:
// direction vectors
const int dx[] = {+1, 0, -1, 0};
const int dy[] = {0, +1, 0, -1};
// matrix dimensions
int row_count;
int col_count;
// the input matrix
int m[MAX][MAX];
// the labels, 0 means unlabeled
int label[MAX][MAX];
void dfs(int x, int y, int current_label) {
if (x < 0 || x == row_count) return; // out of bounds
if (y < 0 || y == col_count) return; // out of bounds
if (label[x][y] || !m[x][y]) return; // already labeled or not marked with 1 in m
// mark the current cell
label[x][y] = current_label;
// recursively mark the neighbors
for (int direction = 0; direction < 4; ++direction)
dfs(x + dx[direction], y + dy[direction], current_label);
}
void find_components() {
int component = 0;
for (int i = 0; i < row_count; ++i)
for (int j = 0; j < col_count; ++j)
if (!label[i][j] && m[i][j]) dfs(i, j, ++component);
}
This is a common way of solving this problem.
The direction vectors are just a nice way to find the neighboring cells (in each of the four directions).
The dfs function performs a depth-first-search of the grid. That simply means it will visit all the cells reachable from the starting cell. Each cell will be marked with current_label
The find_components function goes through all the cells of the grid and starts a component labeling if it finds an unlabeled cell (marked with 1).
This can also be done iteratively using a stack.
If you replace the stack with a queue, you obtain the bfs or breadth-first-search.
This can be solved with union find (although DFS, as shown in the other answer, is probably a bit simpler).
The basic idea behind this data structure is to repeatedly merge elements in the same component. This is done by representing each component as a tree (with nodes keeping track of their own parent, instead of the other way around), you can check whether 2 elements are in the same component by traversing to the root node and you can merge nodes by simply making the one root the parent of the other root.
A short code sample demonstrating this:
const int w = 5, h = 5;
int input[w][h] = {{1,0,0,0,1},
{1,1,0,1,1},
{0,1,0,0,1},
{1,1,1,1,0},
{0,0,0,1,0}};
int component[w*h];
void doUnion(int a, int b)
{
// get the root component of a and b, and set the one's parent to the other
while (component[a] != a)
a = component[a];
while (component[b] != b)
b = component[b];
component[b] = a;
}
void unionCoords(int x, int y, int x2, int y2)
{
if (y2 < h && x2 < w && input[x][y] && input[x2][y2])
doUnion(x*h + y, x2*h + y2);
}
int main()
{
for (int i = 0; i < w*h; i++)
component[i] = i;
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
{
unionCoords(x, y, x+1, y);
unionCoords(x, y, x, y+1);
}
// print the array
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
if (input[x][y] == 0)
{
cout << ' ';
continue;
}
int c = x*h + y;
while (component[c] != c) c = component[c];
cout << (char)('a'+c);
}
cout << "\n";
}
}
Live demo.
The above will show each group of ones using a different letter of the alphabet.
p i
pp ii
p i
pppp
p
It should be easy to modify this to get the components separately or get a list of elements corresponding to each component. One idea is to replace cout << (char)('a'+c); above with componentMap[c].add(Point(x,y)) with componentMap being a map<int, list<Point>> - each entry in this map will then correspond to a component and give a list of points.
There are various optimisations to improve the efficiency of union find, the above is just a basic implementation.
You could also try this transitive closure approach, however the triple loop for the transitive closure slows things up when there are many separated objects in the image, suggested code changes welcome
Cheers
Dave
void CC(unsigned char* pBinImage, unsigned char* pOutImage, int width, int height, int CON8)
{
int i, j, x, y, k, maxIndX, maxIndY, sum, ct, newLabel=1, count, maxVal=0, sumVal=0, maxEQ=10000;
int *eq=NULL, list[4];
int bAdd;
memcpy(pOutImage, pBinImage, width*height*sizeof(unsigned char));
unsigned char* equivalences=(unsigned char*) calloc(sizeof(unsigned char), maxEQ*maxEQ);
// modify labels this should be done with iterators to modify elements
// current column
for(j=0; j<height; j++)
{
// current row
for(i=0; i<width; i++)
{
if(pOutImage[i+j*width]>0)
{
count=0;
// go through blocks
list[0]=0;
list[1]=0;
list[2]=0;
list[3]=0;
if(j>0)
{
if((i>0))
{
if((pOutImage[(i-1)+(j-1)*width]>0) && (CON8 > 0))
list[count++]=pOutImage[(i-1)+(j-1)*width];
}
if(pOutImage[i+(j-1)*width]>0)
{
for(x=0, bAdd=true; x<count; x++)
{
if(pOutImage[i+(j-1)*width]==list[x])
bAdd=false;
}
if(bAdd)
list[count++]=pOutImage[i+(j-1)*width];
}
if(i<width-1)
{
if((pOutImage[(i+1)+(j-1)*width]>0) && (CON8 > 0))
{
for(x=0, bAdd=true; x<count; x++)
{
if(pOutImage[(i+1)+(j-1)*width]==list[x])
bAdd=false;
}
if(bAdd)
list[count++]=pOutImage[(i+1)+(j-1)*width];
}
}
}
if(i>0)
{
if(pOutImage[(i-1)+j*width]>0)
{
for(x=0, bAdd=true; x<count; x++)
{
if(pOutImage[(i-1)+j*width]==list[x])
bAdd=false;
}
if(bAdd)
list[count++]=pOutImage[(i-1)+j*width];
}
}
// has a neighbour label
if(count==0)
pOutImage[i+j*width]=newLabel++;
else
{
pOutImage[i+j*width]=list[0];
if(count>1)
{
// store equivalences in table
for(x=0; x<count; x++)
for(y=0; y<count; y++)
equivalences[list[x]+list[y]*maxEQ]=1;
}
}
}
}
}
// floyd-Warshall algorithm - transitive closure - slow though :-(
for(i=0; i<newLabel; i++)
for(j=0; j<newLabel; j++)
{
if(equivalences[i+j*maxEQ]>0)
{
for(k=0; k<newLabel; k++)
{
equivalences[k+j*maxEQ]= equivalences[k+j*maxEQ] || equivalences[k+i*maxEQ];
}
}
}
eq=(int*) calloc(sizeof(int), newLabel);
for(i=0; i<newLabel; i++)
for(j=0; j<newLabel; j++)
{
if(equivalences[i+j*maxEQ]>0)
{
eq[i]=j;
break;
}
}
free(equivalences);
// label image with equivalents
for(i=0; i<width*height; i++)
{
if(pOutImage[i]>0&&eq[pOutImage[i]]>0)
pOutImage[i]=eq[pOutImage[i]];
}
free(eq);
}
very useful Document => https://docs.google.com/file/d/0B8gQ5d6E54ZDM204VFVxMkNtYjg/edit
java application - open source - extract objects from image - connected componen labeling => https://drive.google.com/file/d/0B8gQ5d6E54ZDTVdsWE1ic2lpaHM/edit?usp=sharing
import java.util.ArrayList;
public class cclabeling
{
int neighbourindex;ArrayList<Integer> Temp;
ArrayList<ArrayList<Integer>> cc=new ArrayList<>();
public int[][][] cclabel(boolean[] Main,int w){
/* this method return array of arrays "xycc" each array contains
the x,y coordinates of pixels of one connected component
– Main => binary array of image
– w => width of image */
long start=System.nanoTime();
int len=Main.length;int id=0;
int[] dir={-w-1,-w,-w+1,-1,+1,+w-1,+w,+w+1};
for(int i=0;i<len;i+=1){
if(Main[i]){
Temp=new ArrayList<>();
Temp.add(i);
for(int x=0;x<Temp.size();x+=1){
id=Temp.get(x);
for(int u=0;u<8;u+=1){
neighbourindex=id+dir[u];
if(Main[neighbourindex]){
Temp.add(neighbourindex);
Main[neighbourindex]=false;
}
}
Main[id]=false;
}
cc.add(Temp);
}
}
int[][][] xycc=new int[cc.size()][][];
int x;int y;
for(int i=0;i<cc.size();i+=1){
xycc[i]=new int[cc.get(i).size()][2];
for(int v=0;v<cc.get(i).size();v+=1){
y=Math.round(cc.get(i).get(v)/w);
x=cc.get(i).get(v)-y*w;
xycc[i][v][0]=x;
xycc[i][v][1]=y;
}
}
long end=System.nanoTime();
long time=end-start;
System.out.println("Connected Component Labeling Time =>"+time/1000000+" milliseconds");
System.out.println("Number Of Shapes => "+xycc.length);
return xycc;
}
}
Please find below the sample code for connected component labeling . The code is written in JAVA
package addressextraction;
public class ConnectedComponentLabelling {
int[] dx={+1, 0, -1, 0};
int[] dy={0, +1, 0, -1};
int row_count=0;
int col_count=0;
int[][] m;
int[][] label;
public ConnectedComponentLabelling(int row_count,int col_count) {
this.row_count=row_count;
this.col_count=col_count;
m=new int[row_count][col_count];
label=new int[row_count][col_count];
}
void dfs(int x, int y, int current_label) {
if (x < 0 || x == row_count) return; // out of bounds
if (y < 0 || y == col_count) return; // out of bounds
if (label[x][y]!=0 || m[x][y]!=1) return; // already labeled or not marked with 1 in m
// mark the current cell
label[x][y] = current_label;
// System.out.println("****************************");
// recursively mark the neighbors
int direction = 0;
for (direction = 0; direction < 4; ++direction)
dfs(x + dx[direction], y + dy[direction], current_label);
}
void find_components() {
int component = 0;
for (int i = 0; i < row_count; ++i)
for (int j = 0; j < col_count; ++j)
if (label[i][j]==0 && m[i][j]==1) dfs(i, j, ++component);
}
public static void main(String[] args) {
ConnectedComponentLabelling l=new ConnectedComponentLabelling(4,4);
l.m[0][0]=0;
l.m[0][1]=0;
l.m[0][2]=0;
l.m[0][3]=0;
l.m[1][0]=0;
l.m[1][1]=1;
l.m[1][2]=0;
l.m[1][3]=0;
l.m[2][0]=0;
l.m[2][1]=0;
l.m[2][2]=0;
l.m[2][3]=0;
l.m[3][0]=0;
l.m[3][1]=1;
l.m[3][2]=0;
l.m[3][3]=0;
l.find_components();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
System.out.print(l.label[i][j]);
}
System.out.println("");
}
}
}
There is an interesting game named one person game. It is played on a m*n grid. There is an non-negative integer in each grid cell. You start with a score of 0. You cannot enter a cell with an integer 0 in it. You can start and end the game at any cell you want (of course the number in the cell cannot be 0). At each step you can go up, down, left and right to the adjacent grid cell. The score you can get at last is the sum of the numbers on your path. But you can enter each cell at most once.
The aim of the game is to get your score as high as possible.
Input:
The first line of input is an integer T the number of test cases. The first line of each test case is a single line containing 2 integers m and n which is the number of rows and columns in the grid. Each of next the m lines contains n space-separated integers D indicating the number in the corresponding cell
Output:
For each test case output an integer in a single line which is maximum score you can get at last.
Constraints:
T is less than 7.
D is less than 60001.
m and n are less than 8.
Sample Input:
4
1 1
5911
1 2
10832 0
1 1
0
4 1
0
8955
0
11493
Sample Output:
5911
10832
0
11493
I tried it but my approach is working very slow for a 7x7 grid.I am trying to access every possible path of the grid recursively and comparing the sum of every path.Below is my code
#include<iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
int max(int a,int b,int c, int d)
{
int max = a;
if(b>max)
max = b;
if(c>max)
max = c;
if(d>max)
max = d;
return max;
}
int Visit_Component( int (*A)[8], int Visit[8][8], int m,int n , int row, int col)
{
if ( ( row >= m ) || (col >= n ) || (col < 0) || (row < 0) || A[row][col] == 0 || Visit[row][col] == 1 )
{
return 0;
}
else
{
Visit[row][col] = 1;
int a= 0,b=0,c=0,d=0,result =0;
a = Visit_Component( A, Visit,m,n, row+1, col);
b = Visit_Component( A, Visit,m,n, row, col +1);
c = Visit_Component( A, Visit,m,n, row, col -1);
d = Visit_Component( A, Visit,m,n, row-1, col );
Visit[row][col] = 0;
result = A[row][col] + max(a,b,c,d);
return result;
}
}
int main(){
int T;
scanf("%d",&T);
for(int k =0; k<T;k++)
{
int N ;
int M;
int count = 0;
int maxcount = 0;
scanf("%d %d",&M,&N);
int C[8][8];
int visit[8][8];
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
{
scanf("%d",&C[i][j]);
visit[i][j] = 0;
}
for( int i= 0 ; i< M ; i++ )
{
for( int j =0; j< N ; j++ )
{
count = Visit_Component( C, visit,M,N, i, j);
if(count > maxcount)
{
maxcount = count;
}
}
}
printf("%d\n",maxcount);
}
return 0;
}
Please suggest me how to optimize this approach or a better algorithm.
As Wikipedia article on Travelling salesman problem suggests, there are exact algorithms, solving this task quickly. But it is hard to find any. And they are, most likely, complicated.
As for optimizing OP's approach, there are several possibilities.
It's easier to start with simple micro-optimization: condition Visit[row][col] == 1 is satisfied with highest probability, so it should come first.
Also it is reasonable to optimize branch-and-bound algorithm with dynamic programming to avoid some repeated calculations. Memorizing calculation results in simple hash table for the cases of up to 19 visited cells improves performance by more than 25% (and more may be expected for some improved hash table). Here is the modified code snippet:
#include<iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
int max(int a,int b,int c, int d)
{
int max = a;
if(b>max)
max = b;
if(c>max)
max = c;
if(d>max)
max = d;
return max;
}
typedef unsigned long long ull;
static const int HS = 10000019;
static const int HL = 20;
struct HT {
ull v;
int r;
int c;
};
HT ht[HS] = {0};
int Visit_Component(
int (*A)[8], ull& Visit, int m,int n , int row, int col, int x)
{
if ( (Visit & (1ull << (8*row+col))) || ( row >= m ) || (col >= n ) ||
(col < 0) || (row < 0) || A[row][col] == 0)
{
return 0;
}
else
{
if (x < HL)
{
HT& h = ht[(Visit+4*row+col)%HS];
if (h.v == Visit && h.r == row && h.c == col)
return 0;
}
Visit |= (1ull << (8*row+col));
int a= 0,b=0,c=0,d=0,result =0;
a = Visit_Component( A, Visit,m,n, row+1, col, x+1);
b = Visit_Component( A, Visit,m,n, row, col +1, x+1);
c = Visit_Component( A, Visit,m,n, row, col -1, x+1);
d = Visit_Component( A, Visit,m,n, row-1, col , x+1);
Visit &= ~(1ull << (8*row+col));
result = A[row][col] + max(a,b,c,d);
if (x < HL)
{
HT& h = ht[(Visit+4*row+col)%HS];
h.v = Visit;
h.r = row;
h.c = col;
}
return result;
}
}
int main(){
int T;
scanf("%d",&T);
for(int k =0; k<T;k++)
{
int N ;
int M;
int count = 0;
int maxcount = 0;
scanf("%d %d",&M,&N);
int C[8][8];
ull visit = 0;
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
{
scanf("%d",&C[i][j]);
}
for( int i= 0 ; i< M ; i++ )
{
for( int j =0; j< N ; j++ )
{
count = Visit_Component( C, visit,M,N, i, j, 0);
if(count > maxcount)
{
maxcount = count;
}
}
}
printf("%d\n",maxcount);
}
return 0;
}
And much more improvements may be done by pre-processing the input matrix. If there are no zeros in the matrix or if there is only one zero in the corner, you may just sum all the values.
If there is only one zero value (not in the corner), at most one non-zero value should be excluded from the sum. If you invent an algorithm, that determines the subset of cells, from which one of the cells must be removed, you can just select the smallest value from this subset.
If there are two or more zero values, use branch-and-bound algorithm: in this case it is about 20 times faster, because each zero value in input matrix means approximately fivefold speed increase.
One optimization that I can think of is to apply Dijkstra's algorithm. This algorithm will give you a minimum (in your case maximum) path for a particular source node to all destination nodes.
In this example, the first step would be to build a graph.
And because you don't know the source node to start at, you will have to apply Dijkstra's algorithm for each node in the grid. The time complexity will be better than your recursion method because for a particular source node, when finding a maximum path Dijkstra's algorithm does not go through all the possible paths.
#include<iostream>
#include<vector>
using namespace std;
vector<vector<int> >A;
vector<vector<bool> >test;
vector<vector<bool> >test1;
int sum_max=0;
int m,n;
vector<vector<bool> > stamp;
void color1(int i,int j,vector<vector<bool> >temp_vector,vector<vector<bool> > st,int summ){
temp_vector[i][j]=false;summ+=A[i][j];st[i][j]=true;
//1.1
if(i+1<m && temp_vector[i+1][j]){
if(test1[i+1][j]){
if(sum_max<(summ)){sum_max=summ;stamp=st;}
}
else{color1(i+1,j,temp_vector,st,summ);}
}
//1.2
if(i+1<m){if(!temp_vector[i+1][j]){ if(sum_max<(summ)){sum_max=summ;}}}
if(i+1>=m){if(sum_max<(summ)){sum_max=summ;}}
//2
if(i-1>=0 && temp_vector[i-1][j]){
if(test1[i-1][j]){
if(sum_max<(summ)){sum_max=summ;}
}
else{ color1(i-1,j,temp_vector,st,summ);}
}
//2.2
if(i-1>=0){if(!temp_vector[i-1][j]){ if(sum_max<(summ)){sum_max=summ;}}}
if(i-1<0){if(sum_max<(summ)){sum_max=summ;}}
//3
if(j+1<n && temp_vector[i][j+1]){
if(test1[i][j+1]){
if(sum_max<(summ)){sum_max=summ;}
}
else{ color1(i,j+1,temp_vector,st,summ);}}
//3.2
if(j+1<n){if(!temp_vector[i][j+1]){ if(sum_max<(summ)){sum_max=summ;}}}
if(j+1>=n){if(sum_max<(summ)){sum_max=summ;}}
//4
if(j-1>=0 && temp_vector[i][j-1]){
if(test1[i][j-1]){
if(sum_max<(summ)){sum_max=summ;}
}
else{ color1(i,j-1,temp_vector,st,summ);}}
//4.2
if(j-1>=0){if(!temp_vector[i][j-1]){ if(sum_max<(summ)){sum_max=summ;}}}
if(j+1<0){if(sum_max<(summ)){sum_max=summ;}}
}
void color(int i,int j){
test[i][j]=false;
if(i+1<m && test[i+1][j]){
color(i+1,j);}
if(i-1>=0 && test[i-1][j]){
color(i-1,j);
}
if(j+1<n && test[i][j+1]){
color(i,j+1);}
if(j-1>=0 && test[i][j-1]){color(i,j-1);}
}
int main(){
int tc;cin>>tc;
for(int i=0;i<tc;i++){
int mp,np;
cin>>mp;
cin>>np;m=mp;n=np;A.resize(m);test.resize(m);test1.resize(m);int sum=0;
vector<bool> ha1(m,1);
vector<bool> ha2(n,1);
for(int i=0;i<m;i++){A[i].resize(n);test[i].resize(n);test1[i].resize(n);
for(int j=0;j<n;j++){
cin>>A[i][j];sum+=A[i][j];
test[i][j]=true;test1[i][j]=false;
if(A[i][j]==0){test[i][j]=false;ha1[i]=false;ha2[j]=false;}
}
}cout<<endl;
for(int i=0;i<m;i++){cout<<" "<<ha1[i];} cout<<endl;
for(int i=0;i<n;i++){cout<<" "<<ha2[i];} cout<<endl;
cout<<"sum "<<sum<<"\n";
int temp_sum=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){//if(A[i][j]<=8845){cout<<"\nk "<<A[i][j]<<" "<<(8845-A[i][j]);}
if(test[i][j]){
if((i-1)>=0 && test[i-1][j] && (i+1)<m && test[i+1][j] && (j-1)>=0 && test[i][j-1] && (j+1)<n && test[i][j+1] && test[i-1][j-1] && test[i-1][j+1]&& test[i+1][j-1] && test[i+1][j+1]){
temp_sum+=A[i][j];test1[i][j]=true;}
}
// cout<<test1[i][j]<<" ";
}//cout<<"\n";
}
// /*
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(test1[i][j]){if(!((test1[i-1][j]||test1[i+1][j]) && (test1[i][j-1]||test1[i][j+1]))){
temp_sum-=A[i][j]; test1[i][j]=false;}
}
//
// cout<<test1[i][j]<<" ";
}//
// cout<<"\n";
}
// */
//cout<<"\n temp_sum is "<<temp_sum<<endl;
vector<vector<bool> > st(m,vector<bool>(n,0));st=test1;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(test[i][j] && (!test1[i][j])){
color1(i,j,test,st,0);
}}}
// cout<<"\nsum is "<<(sum_max+temp_sum)<<endl<<endl;
cout<<(sum_max+temp_sum)<<endl;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){cout<<stamp[i][j]<<" ";} cout<<endl;}
// cout<<max<<endl;
A.clear();
test.clear();
test1.clear();
sum_max=0;
}
cout<<endl;system("pause");
return 0;
}
This question already has answers here:
How to find which elements are in the bag, using Knapsack Algorithm [and not only the bag's value]?
(4 answers)
Closed 2 years ago.
I know how to solve knapsack 0-1 problem with dynamic programming approach, but I am having troubles figuring out which items to take without compromising the complexity of O(N * C) (N items, C capacity).
Any ideas (I would prefer a bottom-up approach)?
Suppose, right now you're storing results in array bool[] a, where a[i] is true when sum i can be achieved.
You'll need another array int[] b, where b[i] is a last element you've placed into knapsack to achieve sum i.
So, where you had
a[i] = true;
you'll need
a[i] = true;
b[i] = current_item;
Then, finding which items can be taken to achieve sum i is a simple loop.
PS I use two arrays for simplicity, but obviously array a can be removed.
Here is a modification to reconstruct path in O(n) times
int knapsack(int weight[], int profit[], int no_of_items, int capacity) {
for (int var = 0; var <= capacity; ++var) {
dp[0][var] = 0;
}
for (int var = 0; var <= no_of_items; ++var) {
path[var] = false;
}
int using_item_i, without_using_item_i;
for (int i = 1; i <= no_of_items; ++i) {
for (int j = 1; j <= capacity; ++j) {
without_using_item_i = dp[i - 1][j];
using_item_i = 0;
if ((weight[i]) <= j) {
using_item_i = dp[i - 1][j - weight[i]] + profit[i];
}
if (using_item_i >= without_using_item_i) {
taken[i][j] = true;
dp[i][j] = using_item_i;
} else {
taken[i][j] = false;
dp[i][j] = without_using_item_i;
}
}
}
//Reconstructing back the path
int j = capacity;
for (int i = no_of_items; i >= 0; --i) {
if (taken[i][j]) {
path[i] = true;
cnt++;
}
j = j - weight[i];
}
return dp[no_of_items][capacity];
}
boolean[] solution = new boolean[nItems];
for (int i = nItems, c = maxCapacity; i > 0 && c > 0; i--) {
int iThItemAddedValue = value[i - 1][c - weights[i - 1]] + values[i - 1];
int iThItemInheritedValue = value[i - 1][c];
if (iThItemAddedValue > iThItemInheritedValue) {
solution[i - 1] = true;
c = c - weights[i - 1];
} else {
solution[i - 1] = false;
}
}
Check the sol in the attached image
public class Knapsackproblem {
private static int[][] cache;
public static void main(String[] args) {
int val[] = new int[]{60, 100, 120};
int wt[] = new int[]{10, 20, 30};
int W = 50;
int n = val.length;
System.out.println(knapSack(W, wt, val, n));
printValues(wt,val);
}
/**
* This method will find the result with
* more value with weight less than or equal
* to given weight
* #param w given weight
* #param wt arrays of weights
* #param val array of values
* #param n length of the array
* #return max value we can obtain
*/
private static int knapSack(int w, int[] wt, int[] val, int n) {
cache = new int[n+1][w+1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= w; j++) {
if(j < wt[i-1]){
cache[i][j] = cache[i-1][j];
}else {
cache[i][j] = Math.max(cache[i-1][j],(cache[i-1][j-wt[i-1]])+val[i-1]);
}
}
}
for (int[] aCache : cache) {
System.out.println(Arrays.toString(aCache));
}
return cache[n][w];
}
private static void printValues(int[] wt, int[] val) {
int m = cache.length-1;
int n = cache[0].length-1;
util(wt,val,m,n);
}
private static void util(int[] wt, int[] val, int m, int n) {
if(m <=0 || n<=0) return;
if((cache[m][n] != cache[m-1][n]) && (cache[m][n] != cache[m][n-1])){
System.out.println(val[m-1]+"-->"+wt[m-1]);
util(wt, val, m-1, (n - wt[m - 1] + 1));
}else
if(cache[m][n] == cache[m-1][n]){
util(wt,val,m-1,n);
}
else if(cache[m][n] == cache[m][n-1])
util(wt,val,m,n-1);
else
util(wt,val,m,(n-val[m-1]+1));
}
}
https://www.dropbox.com/s/ish7t5vgy91fovt/Screenshot%202017-01-01%2015.16.31.png?dl=0
Print the tmpList in the caller and you will get the answer