什么可以是单排摩天大楼拼图的节省空间的算法

我试图解决一个问题,这是
skyscraper puzzle的单行变体.问题陈述是:

考虑一个大小为nxn的摩天大楼拼图的单行.如果我们知道从左侧和右侧可以看到多少栋建筑物,那么有多少种不同的方式可以填充高度为1..n的建筑物? (1 <<; = N&LT = 5000) 我用自下而上的动态编程来解决它.递归关系如下:

f(n,left,right)=(n-2)*f(n-1,left,right) + f(n-1,left-1,right) +f(n-1,left,right-1)
f[1][1][1]=1;

不要担心答案中的大数字,因为我应该显示模数结果.我能够从中得到正确答案,但此算法的内存要求非常高.空间复杂度为O(n ^ 3),这对于给定的问题来说太多了,因为n可以高达5,000.

你能建议我一些替代算法吗?

编辑:

为了解释我的复发关系:
考虑所有与(n-1)高度的组合,现在为所有建筑增加1个高度.这将使我们的建筑物从2,3到n.现在只需要调整高度为1的建筑物.它可以在任何一侧调整,这是第二和第三项int添加.
如果它不插入侧面,那么另外用第一项表示.如果目前还不清楚,请告诉我,我真的很感激任何帮助

最佳答案 好的,要解决这个问题,我们需要做几点观察:

>首先,最高的建筑将左右分开视图,因此,如果我们可以决定最高建筑的位置,我们可以分开解决左右视图问题.
>假设我们有一个函数f(x,n),它计算出我们可以从一侧看到n个建筑物中的x个建筑物的方式.因此,在我们确定最高建筑物的位置后,结果将是f(左 – 1,a – 1)* f(右 – 1,n – a – 1)* c(a – 1,n – 1) a是最高建筑物的位置,a – 1将是最高建筑物左侧的建筑物数量,功能c(a – 1,n – 1)计算选择a – 1建筑物的方式在n – 1栋建筑物中(因为我们需要随机挑选一栋1至1栋建筑物放在左侧).

因此,我们可以创建一个dp [n] [n]表来存储函数f(x,n)的结果.对于最高建筑的每个位置a:

我们有答案= dp [left – 1] [a – 1] * d [right – 1] [n – a – 1] * c [a – 1] [n – 1].

要计算O(n ^ 2)时间复杂度中的表dp [n] [n],我们需要做一些其他的观察:

>对于每个dp [x] [y],我们有dp [x] [y] = dp [x – 1] [y – z – 1] * P(z,y – 1)之和,这意味着我们选择z建筑物并在最高的建筑物后随机隐藏(最高的建筑物总是计入那些看到的建筑物中).函数P是计算排列.
>因为P(a,b)= b! /(b – a)!,所以,我们可以看到,如果我们使用额外的数组总数,存储总数[x] = dp [x] [y] / y !,我们有:

 dp[x][y] = total[x - 1]* (y - 1)!
          = (dp[x - 1][0]/0! + dp[x -1][1]/1! + ... + dp[x - 1][y - 1]/ (y -1)!)*(y - 1)!
          = dp[x - 1][0]*P(y - 1, y - 1) + dp[x - 1][1]*P(y - 2, y - 1) + ... 

因此,我们可以在O(n ^ 2)中计算dp:

 for(int y = 1; y <= n; y++){
     for(int x = 1; x <= y; x++){
         dp[x][y] = total[x - 1]*(y - 1)!;
         total[x] += dp[x][y]/y!;
     }
 }

通过这个,我们完成了我们的问题,将时间和空间复杂度保持在O(n ^ 2).

注意:经过problem statement之后,我们需要计算mod 1000,000,007的路数,所以你应该使用模数逆来解决这个问题,这也有助于避免精度问题.

点赞