6

我正在阅读 Dumitru 的这篇关于基于 DP 的问题的优秀教程。我正在尝试为一维 DP 问题列表中提到的FlowerGarden问题提出一种基于 DP 的方法。

我只能想到一个非 DP 解决方案,该解决方案将涉及最初按顺序对花朵进行排序,然后根据问题中提到的不同条件检查对它们重新排序。那不归类为DP,是吗?

社论也没有提到任何关于DP的事情。任何人都可以向我指出一个适当的基于 DP 的解决方案来解决这个问题吗?

谢谢!

编辑:

我没有意识到该链接需要注册。这就是问题:

问题陈述您正在种植一个带球茎的花园,以便全年为您提供欢乐的花朵。但是,您希望种植花朵,使其在可见时不会阻挡其他花朵。

您将获得一个 int[] 高度、一个 int[] 绽放和一个 int[] 枯萎。每种类型的花都由具有相同高度、开花和枯萎指数的元素表示。高度代表每种花的生长高度,绽放代表每种花从地里长出来的早晨,枯萎代表每种花枯萎死亡的晚上。bloom 和 wilt 中的每个元素都是介于 1 和 365 之间的数字,并且 wilt[i] 将始终大于 bloom[i]。您必须将相同类型的所有花朵都种植在同一行中以保持外观,并且您还希望将最高的花朵尽可能向前。但是,如果一种花型比另一种花型高,而且两种花型可以同时出土,较短的花必须种植在较高的花前面,以防止阻塞。一朵花早上开花,晚上枯萎,所以即使一朵花在同一天开花,另一朵花在枯萎,一朵也可以挡住另一朵。

您应该返回一个包含高度元素的 int[],您应该按照种植花的顺序来实现上述目标。花园的前面由返回值中的第一个元素表示,是您查看花园的位置。高度的元素都是唯一的,所以总是有一个明确定义的顺序。

编辑二:

示例 1:

高度={5,4,3,2,1}

绽放={1,1,1,1,1}

枯萎={365,365,365,365,365}

返回:{ 1, 2, 3, 4, 5 }

这些花都在1月1日开花,12月31日枯萎。由于它们都可能相互阻挡,因此您必须将它们从最短到最高排序。

示例 2:

h={5,4,3,2,1}

b={1,5,10,15,20}

w={4,9,14,19,24}

返回: { 5, 4, 3, 2, 1 } 同一组花现在在不同的时间开花。由于它们永远不会互相阻挡,因此您可以将它们从最高到最短排序,以使最高的尽可能靠前。

示例 3:高度={5,4,3,2,1}

绽放={1,5,10,15,20}

枯萎={5,10,14,20,25}

返回: { 3, 4, 5, 1, 2 } 这里的区别是第三种花比第四朵花早一天枯萎。因此,我们可以先放置高度为 3 的花朵,然后放置高度为 4 的花朵,然后放置高度为 5 的花朵,最后放置高度为 1 和 2 的花朵。请注意,我们也可以先订购高度为 1 的花朵,但这并没有导致最大可能的高度首先出现在花园中。

4

11 回答 11

4

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]
于 2015-04-11T18:24:48.967 回答
2
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;
}

这是我经过测试的工作代码。

于 2014-03-28T08:10:34.947 回答
1

我一整天都在为这个确切的问题苦苦挣扎,而且我找不到任何 DP 解决方案。

这是我在java中的贪婪方法,类似于其他已经发布的方法,关键是在高度排序下进行。原因是避免处理中间高度(指已经计算的),因为中间高度可以改变先前计算的高度的相对顺序

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)));

这是我能找到的唯一最优子结构。但是考虑到子问题之间没有重叠,这个算法不应该被认为是DP,而是贪婪的。

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;
}

顺便说一句,我在这里看到的 DP 解决方案在此示例中失败。

干杯

于 2017-02-03T08:26:32.037 回答
0

拓扑排序方法:

#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]));

}
于 2013-11-23T03:57:57.293 回答
0
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]);
        }
    }
}
于 2013-06-15T01:47:16.193 回答
0

我也试图解决这个问题。我的方法的主要思想是构建一棵树,其中每个孩子至少被其父母重叠一次。

例如,如果我们有三种高度为 4,2 和 1 的花在同一天生长和死亡,那么生成的树应该是:

所有节点重叠

另一方面,如果 4 和 2 以及 4 和 1 同时存在但 2 和 1 不共存,那么生成的树应该是:

两兄弟

这将生成一棵与问题约束一致的树。尽管如此,问题陈述还包括成本函数,使某些解决方案比其他解决方案更好。

...您还希望使更靠前的成排花朵尽可能高。

将这种偏好投射到我们的树中的方法是将所有“兄弟”(所有节点共享相同的父节点)从高到低排序。所以 2 先于 1。

我使用以下代码构建了这棵树:

#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);

此时,的每一行 (i)包含按从高到低排序的所有花卉类型索引,这些索引应该放在索引i的花卉类型之前。

需要最后一步,将展平为输出向量。也就是说,要构建一个向量,其中每个元素后跟:

  • 它的父级在树上。
  • 它的下一个兄弟按身高排序。

这可以通过对group的每个节点进行深度访问来完成。我认为这是我的解决方案的弱点。我没有太多时间,所以我只是做了一个简单的递归实现:

//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);
}

其中用于完成 getOrdering 功能:

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; 
}

请让我知道您是否找到了更好的解决方案或者是否知道任何改进我的方法。

于 2013-05-21T11:43:38.493 回答
0

我的就像插入排序。对于每一朵新花,它从后到前检查它前面的那朵是否挡住了它;如果是这样,则意味着它必须放在它后面。同样,它也会从前向后搜索并检查它后面的人是否阻止它;如果是这样,则意味着它必须放在它的前面。如果没有块,它只会检查最佳点高度。

#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");
    }
}

编辑:这个解决方案太糟糕了,我想出了一个更好的解决方案,实际上是 DP;如下:对于每朵花,循环遍历所有其他花,检查它阻塞了哪些花;对于它挡住的那些花,检查它挡住的所有花,依此类推,直到你找到一朵不会挡住其他花的花。把那朵花放在一个新的阵列中。回溯并将每朵花放在新数组的下一个插槽中。如果对每一朵花都完成了,你会得到一个满是花的阵列,它们不会阻挡任何其他的花。然后,您将每朵花尽可能地放在前面。这个解决方案的 DP 部分是有时你会遇到之前已经被另一朵花挡住并且已经放入新数组的同一朵花,所以我们跳过那朵花而不是追赶它挡住的花。

于 2017-03-26T01:20:48.680 回答
0

我已经用 c++ 实现了。我使用向量数据类型分别存储高度、绽放和枯萎,然后我将其排序到高度,然后我一朵朵地取花并根据与它们相关的值排列它们。

这是代码:-

#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;

}
于 2018-08-20T17:19:04.803 回答
0

与 Rob 类似,再次使用 Python 和稍微复杂的重叠开花/枯萎检查。

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]
于 2016-05-14T13:25:17.963 回答
0

与 Rob 相同,但在 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] );
}
于 2015-11-07T14:08:37.387 回答
0

解决问题的图算法:

创建一个有向图(V,E):V -> 花型 E -> 2 种花型之间的关系

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

有关更多描述,请查看此论坛: Topcoder 论坛 - FlowerGarden

于 2016-07-02T07:23:39.143 回答