我遇到了这个问题
ADZEN是您所在城市非常受欢迎的广告公司。在每一条路上 你可以看到他们的广告牌。最近他们面临着一个问题 严峻的挑战,MG道路中最常用,最美丽的道路 城市几乎被广告牌所填满,这是一个 对...的负面影响 自然观。 根据人们的需求,ADZEN决定拆除一些广告牌 以这种方式,只有K个广告牌站在一起 在任何一条路上。 你可以假设MG Road是一条带有N个广告牌的直线。最初两个adjecent之间没有差距 广告牌。 ADZEN的主要收入来自这些广告牌,因此广告牌移除过程必须以这样的方式完成 广告牌 保留在最后应该在所有可能的最终配置中给出最大可能的利润。配置的总利润是 所有广告牌的利润价值总和 组态。 给定N,K和N个广告牌中的每一个的利润值,输出可以从剩余的广告牌中获得的最大利润 在给定条件下的广告牌。
输入说明
第1行包含两个空格分隔的整数N和K.然后按N行描述每个广告牌的利润值,即ith line包含第i个广告牌的利润值。
Sample Input 6 2 1 2 3 1 6 10 Sample Output 21
解释
在给定的输入中有6个广告牌,在此过程之后不应超过2个。所以删除第1和第4 给出配置的广告牌_2 3 _ 6 10,利润为21。 没有其他配置的利润超过21.所以答案是21。
Constraints 1 <= N <= 1,00,000(10^5) 1 <= K <= N 0 <= profit value of any billboard <= 2,000,000,000(2*10^9)
我认为我们必须在第一个k + 1板上选择最低成本板,然后重复相同的直到最后,但这没有给出正确的答案 对于所有情况。 我尝试了我的知识,但无法找到解决方案。 如果有人有想法,请分享你的想法。
答案 0 :(得分:12)
这是典型的DP问题。让我们说P(n,k)是将k个广告牌放到道路上的位置n的最大利润。然后你有以下公式:
P(n,k) = max(P(n-1,k), P(n-1,k-1) + C(n))
P(i,0) = 0 for i = 0..n
其中c(n)是将第n个广告牌放在路上的利润。使用该公式计算P(n,k)自下而上,你将在O(nk)时间内得到解决方案。
我会留意你找出为什么这个公式成立。
修改强>
方,我误解了这个问题。它仍然是DP问题,只是公式不同。假设P(v,i)表示最后一组广告牌的大小为i的点v的最大利润。 然后可以使用以下公式描述P(v,i):
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
您需要找到max(P(n,i) for i = 0..k))
。
答案 1 :(得分:1)
此问题是www.interviewstreet.com上发布的挑战之一...
我很高兴地说我最近得到了这个,但不太满意,想看看那里是否有更好的方法。
灵魂检查上面的DP解决方案很简单,但由于K可以和N一样大,所以无法完全解决这个问题,这意味着DP复杂度对于运行时和空间都是O(NK)。 / p>另一个解决方案是进行分支绑定,跟踪到目前为止的最佳总和,并在某个级别修剪递归,也就是说,如果currSumSoFar + SUM(a [currIndex..n))&lt; = bestSumSoFar ...然后立即退出函数,当上限到目前为止不会超过最佳总和时,没有进一步处理的点。
除了2个测试用例之外,测试人员都接受了上面的分支绑定。 幸运的是,我注意到2个测试用例使用小K(在我的情况下,K <300),因此O(NK)的DP技术就足够了。
答案 2 :(得分:1)
soulcheck(第二)DP解决方案原则上是正确的。您可以使用这些观察结果进行两项改进:
1)不必分配整个DP表。你一次只能看两行。
2)对于每一行(P(v,i)中的v),您只对最大增加最大值的i感兴趣,这比在前一行中保持最大值的每个i多一个。此外,i = 1,否则你永远不会考虑空白。
答案 3 :(得分:1)
我使用DP in O(nlogk)在c ++中编码。 想法是为给定位置维持具有下一个k值的多集。该多集合通常在中间处理中具有k值。每次移动元素并推送新元素。艺术是如何保持这个列表有利润[i] +回答[i + 2]。关于集合的更多细节:
/* * Observation 1: ith state depends on next k states i+2....i+2+k * We maximize across this states added on them "accumulative" sum * * Let Say we have list of numbers of state i+1, that is list of {profit + state solution}, How to get states if ith solution * * Say we have following data k = 3 * * Indices: 0 1 2 3 4 * Profits: 1 3 2 4 2 * Solution: ? ? 5 3 1 * * Answer for [1] = max(3+3, 5+1, 9+0) = 9 * * Indices: 0 1 2 3 4 * Profits: 1 3 2 4 2 * Solution: ? 9 5 3 1 * * Let's find answer for [0], using set of [1]. * * First, last entry should be removed. then we have (3+3, 5+1) * * Now we should add 1+5, but entries should be incremented with 1 * (1+5, 4+3, 6+1) -> then find max. * * Could we do it in other way but instead of processing list. Yes, we simply add 1 to all elements * * answer is same as: 1 + max(1-1+5, 3+3, 5+1) * */
ll dp()
{
multiset<ll, greater<ll> > set;
mem[n-1] = profit[n-1];
ll sumSoFar = 0;
lpd(i, n-2, 0)
{
if(sz(set) == k)
set.erase(set.find(added[i+k]));
if(i+2 < n)
{
added[i] = mem[i+2] - sumSoFar;
set.insert(added[i]);
sumSoFar += profit[i];
}
if(n-i <= k)
mem[i] = profit[i] + mem[i+1];
else
mem[i] = max(mem[i+1], *set.begin()+sumSoFar);
}
return mem[0];
}
答案 4 :(得分:0)
这看起来像是线性编程问题。这个问题是线性的,但是要求不超过K个相邻的广告牌可能会保留。
有关一般治疗,请参阅维基百科:http://en.wikipedia.org/wiki/Linear_programming
访问您的大学图书馆,找到有关该主题的优秀教科书。
有许多库可以帮助进行线性编程,因此我建议您不要尝试从头开始编写算法。以下是与Python相关的列表:http://wiki.python.org/moin/NumericAndScientific/Libraries
答案 5 :(得分:0)
如果我们删除广告牌P[i]
,则1..i
(其中i = 1..n)是广告牌i
的最大利润。知道所有P [i],计算答案是微不足道的。计算P [i]的基线算法如下:
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] );
}
}
现在这个想法可以让我们加快速度。我们假设我们只有两种不同的有效配置广告牌1
到i
,让我们将这些配置称为X1
和X2
。如果在配置i
和X1
中移除了广告牌profit(X1) >= profit(X2)
,那么我们应该始终更喜欢配置X1
广告牌1..i
(profit()
我的意思是仅从广告牌1..i
中获利,无论i+1..n
的配置如何)。这很重要,显而易见。
我们引入了一个双重链接的元组列表{idx,d}
:{{idx1,d1}, {idx2,d2}, ..., {idxN,dN}}
。
p->idx
是删除的最后一个广告牌的索引。我们通过列表时p->idx
正在增加:p->idx < p->next->idx
p->d
不是列表中的最后一个元素,则(C[p->idx]+C[p->idx+1]+..+C[p->next->idx-1])
是元素p
的总和。否则,它是直到当前位置的元素总和减1:(C[p->idx]+C[p->idx+1]+..+C[i-1])
。以下是算法:
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]
}
答案 6 :(得分:0)
//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