📜  门| GATE MOCK 2017 |问题18(1)

📅  最后修改于: 2023-12-03 15:42:14.761000             🧑  作者: Mango

门 | GATE MOCK 2017 | 问题18

这是一道GATE MOCK 2017的编程题,需要使用动态规划算法解决。题目描述如下:

有n个门,每扇门只能通过其上方的砖块进入。其中第1扇门最初是开着的,第n扇门最终也需要开启,其他的门可以打开或关闭。在每个门上方的砖块有不同的重量,如果一个门是关闭的,则该门上方的砖块不能再次使用。

假设每个门的高度均相同,而每个门上方的砖块可以通过不同的加入方法使其达到所需高度。现在给出每个门上方的砖块的重量,以及加入每扇门所需的砖块的集合。

请编写程序,找到使第n扇门打开的方案中最大的砖块重量总和。

接下来,我们将逐步讲解如何解决这个问题。

题目分析

给定任意两个门的编号p和q,我们将它们之间的门称为“障碍物”。在这个问题中,如果一个门是关闭的,我们将其视为一个障碍物。

因此,我们可以根据障碍物情况来定义状态。

假设状态f(i,j)表示到第i个门为止,第i个门当前关闭,且第i+1到第j-1个门都是开着的,第j个门也必须开启,所需的最大砖块重量总和。

根据这个定义,我们可以方便地定义状态转移方程。

状态转移方程
  1. 当i=j时,f(i,j)=0,这是一个初始状态。

  2. 当i<j时:

    • 如果第i个门已经开着,f(i,j)=f(i+1,j),第i个门不需要再次考虑。
    • 如果第i个门关闭,f(i,j)=Maxwi+f(i+1,k)+f(k+1,j),其中k为i+1到j-1之间的任意一个门。在这种情况下,我们需要从所有可能的门之间的分裂中选择最小重量总和。

由此,我们可以使用以下代码实现状态转移方程:

dp = [[0 for i in range(n)] for j in range(n)]
for len in range(2, n+1):
    for i in range(n-len+1):
        j = i + len -1
        if (j-i+1)==2:
            dp[i][j] = 0
        else:
            tmp = 10**9
            for k in range(i+1, j):
                val = dp[i][k] + dp[k][j] + weights[j]-weights[i]-2
                tmp = min(tmp, val)
            dp[i][j] = tmp
返回值

最后,我们需要返回f(1,n)的值。

return dp[0][n-1]
总结

这道题是一道经典的动态规划问题,需要考虑问题的障碍物和可能的分割。状态转移方程的实现可能比较复杂,需要仔细思考。