Removal of billboards from given ones

前端 未结 7 1909
Happy的楠姐
Happy的楠姐 2020-12-14 11:46

I came across this question

ADZEN is a very popular advertising firm in your city. In every road you can see their advertising billboards. Recentl

相关标签:
7条回答
  • 2020-12-14 12:19

    This looks like a linear programming problem. This problem would be linear, but for the requirement that no more than K adjacent billboards may remain.

    See wikipedia for a general treatment: http://en.wikipedia.org/wiki/Linear_programming

    Visit your university library to find a good textbook on the subject.

    There are many, many libraries to assist with linear programming, so I suggest you do not attempt to code an algorithm from scratch. Here is a list relevant to Python: http://wiki.python.org/moin/NumericAndScientific/Libraries

    0 讨论(0)
  • 2020-12-14 12:21

    Let P[i] (where i=1..n) be the maximum profit for billboards 1..i IF WE REMOVE billboard i. It is trivial to calculate the answer knowing all P[i]. The baseline algorithm for calculating P[i] is as follows:

    for i=1,N
    {
      P[i]=-infinity;
      for j = max(1,i-k-1)..i-1
      {
        P[i] = max( P[i], P[j] + C[j+1]+..+C[i-1] );
      }
    }
    

    Now the idea that allows us to speed things up. Let's say we have two different valid configurations of billboards 1 through i only, let's call these configurations X1 and X2. If billboard i is removed in configuration X1 and profit(X1) >= profit(X2) then we should always prefer configuration X1 for billboards 1..i (by profit() I meant the profit from billboards 1..i only, regardless of configuration for i+1..n). This is as important as it is obvious.


    We introduce a doubly-linked list of tuples {idx,d}: {{idx1,d1}, {idx2,d2}, ..., {idxN,dN}}.

    • p->idx is index of the last billboard removed. p->idx is increasing as we go through the list: p->idx < p->next->idx
    • p->d is the sum of elements (C[p->idx]+C[p->idx+1]+..+C[p->next->idx-1]) if p is not the last element in the list. Otherwise it is the sum of elements up to the current position minus one: (C[p->idx]+C[p->idx+1]+..+C[i-1]).

    Here is the algorithm:


    P[1] = 0;
    list.AddToEnd( {idx=0, d=C[0]} );
    // sum of elements starting from the index at top of the list
    sum = C[0]; // C[list->begin()->idx]+C[list->begin()->idx+1]+...+C[i-1]
    for i=2..N
    {
      if( i - list->begin()->idx > k + 1 ) // the head of the list is "too far"
      {
        sum = sum - list->begin()->d
        list.RemoveNodeFromBeginning()
      }
      // At this point the list should containt at least the element
      // added on the previous iteration. Calculating P[i].
      P[i] = P[list.begin()->idx] + sum
      // Updating list.end()->d and removing "unnecessary nodes"
      // based on the criterion described above
      list.end()->d = list.end()->d + C[i]
      while(
        (list is not empty) AND
        (P[i] >= P[list.end()->idx] + list.end()->d - C[list.end()->idx]) )
      {
        if( list.size() > 1 )
        {
          list.end()->prev->d += list.end()->d
        }
        list.RemoveNodeFromEnd();
      }
      list.AddToEnd( {idx=i, d=C[i]} );
      sum = sum + C[i]
    }
    
    0 讨论(0)
  • 2020-12-14 12:23

    It's a typical DP problem. Lets say that P(n,k) is the maximum profit of having k billboards up to the position n on the road. Then you have following formula:

     P(n,k) = max(P(n-1,k), P(n-1,k-1) + C(n))
     P(i,0) = 0 for i = 0..n
    

    Where c(n) is the profit from putting the nth billboard on the road. Using that formula to calculate P(n, k) bottom up you'll get the solution in O(nk) time.

    I'll leave up to you to figure out why that formula holds.

    edit

    Dang, I misread the question.

    It still is a DP problem, just the formula is different. Let's say that P(v,i) means the maximum profit at point v where last cluster of billboards has size i. Then P(v,i) can be described using following formulas:

    P(v,i) = P(v-1,i-1) + C(v) if i > 0 
    P(v,0) = max(P(v-1,i) for i = 0..min(k, v)) 
    P(0,0) = 0
    

    You need to find max(P(n,i) for i = 0..k)).

    0 讨论(0)
  • 2020-12-14 12:23

    This problem is one of the challenges posted in www.interviewstreet.com ...

    I'm happy to say I got this down recently, but not quite satisfied and wanted to see if there's a better method out there.

    soulcheck's DP solution above is straightforward, but won't be able to solve this completely due to the fact that K can be as big as N, meaning the DP complexity will be O(NK) for both runtime and space.

    Another solution is to do branch-and-bound, keeping track the best sum so far, and prune the recursion if at some level, that is, if currSumSoFar + SUM(a[currIndex..n)) <= bestSumSoFar ... then exit the function immediately, no point of processing further when the upper-bound won't beat best sum so far.

    The branch-and-bound above got accepted by the tester for all but 2 test-cases. Fortunately, I noticed that the 2 test-cases are using small K (in my case, K < 300), so the DP technique of O(NK) suffices.

    0 讨论(0)
  • 2020-12-14 12:23
    //shivi..coding is adictive!!
    #include<stdio.h>
    
    long long int arr[100001];
    long long  int sum[100001];
    long long  int including[100001],excluding[100001];
    long long int maxim(long long int a,long long int b)
    {if(a>b) return a;return b;}
    
    int main()
    {
    int N,K;
    scanf("%d%d",&N,&K);
    for(int i=0;i<N;++i)scanf("%lld",&arr[i]);
    
    sum[0]=arr[0];
    including[0]=sum[0];
    excluding[0]=sum[0];
    for(int i=1;i<K;++i)
    {
        sum[i]+=sum[i-1]+arr[i];
        including[i]=sum[i];
        excluding[i]=sum[i];
    }
    
    long long int maxi=0,temp=0;
    for(int i=K;i<N;++i)
    {
        sum[i]+=sum[i-1]+arr[i];
        for(int j=1;j<=K;++j)
        {
            temp=sum[i]-sum[i-j];
            if(i-j-1>=0)
            temp+=including[i-j-1];
            if(temp>maxi)maxi=temp;
        }
        including[i]=maxi;
        excluding[i]=including[i-1];
    }
    printf("%lld",maxim(including[N-1],excluding[N-1]));
    }
    
    //here is the code...passing all but 1 test case :) comment improvements...simple DP
    
    0 讨论(0)
  • 2020-12-14 12:33

    soulcheck's (second) DP solution is correct in principle. There are two improvements you can make using these observations:

    1) It is unnecessary to allocate the entire DP table. You only ever look at two rows at a time.

    2) For each row (the v in P(v, i)), you are only interested in the i's which most increase the max value, which is one more than each i that held the max value in the previous row. Also, i = 1, otherwise you never consider blanks.

    0 讨论(0)
提交回复
热议问题