电影院座位安排需要兼顾观众舒适度、座位利用率和运营成本,当我们需要从现有座位序列中筛选出符合特定条件且成本最低的子序列时,动态规划是一种高效的解决思路,能够避免暴力枚举带来的高时间复杂度问题。

问题场景定义
假设电影院的座位按行排列,每个座位有一个对应的运营成本,同时需要满足相邻选中的座位之间至少间隔k个空位的要求,目标是从所有座位中选出若干个座位,使得总运营成本最低,且符合间隔要求。我们可以将座位序列看作一个一维数组,问题转化为在这个数组中寻找满足间隔约束的最低成本子序列。
动态规划算法设计
状态定义
我们定义dp[i]表示考虑前i个座位时,能达到的最低运营成本。这里需要注意,状态需要区分第i个座位是否被选中,因此我们可以扩展状态为二维:dp[i][0]表示前i个座位中,第i个座位未被选中时的最低成本;dp[i][1]表示前i个座位中,第i个座位被选中时的最低成本。
转移方程推导
根据状态定义,我们可以得到转移逻辑:
- 如果第i个座位不被选中,那么前i-1个座位可以是任意状态,因此
dp[i][0] = min(dp[i-1][0], dp[i-1][1]) - 如果第i个座位被选中,那么第i-k个座位必须不被选中(保证间隔k个空位),因此
dp[i][1] = cost[i] + min(dp[i-k-1][0], dp[i-k-1][1]),这里需要注意i-k-1不能小于0,小于0时取0作为基础成本
初始条件与结果计算
初始时,dp[0][0] = 0,dp[0][1] = 无穷大,因为不存在第0个座位被选中的情况。最终结果为min(dp[n][0], dp[n][1]),其中n是座位总数。
代码实现示例
以下是基于Python语言的完整实现,包含边界条件处理:
def min_seat_cost(cost_list, k):
n = len(cost_list)
if n == 0:
return 0
# 初始化dp数组,dp[i][0]表示第i个座位不选,dp[i][1]表示第i个座位选
dp = [[0, 0] for _ in range(n+1)]
# 无穷大表示不可达状态
dp[0][1] = float('inf')
for i in range(1, n+1):
# 第i个座位不选的情况,取前i-1个座位的最小成本
dp[i][0] = min(dp[i-1][0], dp[i-1][1])
# 第i个座位选的情况,需要前i-k-1个座位的最小成本加上当前座位成本
prev_idx = i - k - 1
if prev_idx <= 0:
# 前面没有足够的座位满足间隔要求,直接取当前座位成本
dp[i][1] = cost_list[i-1]
else:
dp[i][1] = cost_list[i-1] + min(dp[prev_idx][0], dp[prev_idx][1])
return min(dp[n][0], dp[n][1])
# 测试示例:5个座位,成本分别为[3, 2, 5, 1, 4],间隔要求k=1(选中座位之间至少隔1个空位)
seat_costs = [3, 2, 5, 1, 4]
interval_k = 1
result = min_seat_cost(seat_costs, interval_k)
print(f"最低座位运营成本为:{result}")
算法复杂度分析
该算法只需要遍历一次座位序列,每个状态的计算都是常数时间,因此时间复杂度为O(n),其中n是座位总数。空间复杂度方面,我们使用了一个长度为n+1的二维数组,因此空间复杂度为O(n),如果进一步优化可以只保留前k+1个状态,将空间复杂度降低到O(k)。
实际场景扩展
上述算法可以扩展到更多实际场景,比如增加座位优先级权重、不同区域的座位成本不同、允许不同间隔要求等。只需要在状态转移时加入对应的约束条件即可,核心的动态规划思路保持不变。这种基于动态规划的子序列优化方法,同样可以应用到其他类似的序列选择问题中,比如资源分配、任务调度等场景。