Leetcode LCP 47:入场安检

题目:

「力扣挑战赛」 的入场仪式马上就要开始了,由于安保工作的需要,设置了可容纳人数总和为 M 的 N 个安检室,capacities[i] 记录第 i 个安检室可容纳人数。安检室拥有两种类型:

先进先出:在安检室中的所有观众中,最早进入安检室的观众最先离开
后进先出:在安检室中的所有观众中,最晚进入安检室的观众最先离开


恰好 M+1 位入场的观众(编号从 0 开始)需要排队依次入场安检, 入场安检的规则如下:

观众需要先进入编号 0 的安检室
当观众将进入编号 i 的安检室时(0 <= i < N),
若安检室未到达可容纳人数上限,该观众可直接进入;
若安检室已到达可容纳人数上限,在该观众进入安检室之前需根据当前安检室类型选择一位观众离开后才能进入;
当观众离开编号 i 的安检室时 (0 <= i < N-1),将进入编号 i+1 的安检室接受安检。
若可以任意设定每个安检室的类型,请问有多少种设定安检室类型的方案可以使得编号 k 的观众第一个通过最后一个安检室入场。

注意:

观众不可主动离开安检室,只有当安检室容纳人数达到上限,且又有新观众需要进入时,才可根据安检室的类型选择一位观众离开;
由于方案数可能过大,请将答案对 1000000007 取模后返回。
示例 1:

输入:capacities = [2,2,3], k = 2

输出:2
解释:
存在两种设定的 2 种方案:

方案 1:将编号为 0 、1 的实验室设置为 后进先出 的类型,编号为 2 的实验室设置为 先进先出 的类型;
方案 2:将编号为 0 、1 的实验室设置为 先进先出 的类型,编号为 2 的实验室设置为 后进先出 的类型。

示例 2:

输入:capacities = [3,3], k = 3

输出:0

示例 3:

输入:capacities = [4,3,2,2], k = 6

输出:2

提示:

1 <= capacities.length <= 200
1 <= capacities[i] <= 200
0 <= k <= sum(capacities)

代码:

class Solution {
public:
    int securityCheck(vector<int>& capacities, int k) {
        int len=capacities.size();
    int base=1000000007;
    vector<vector<int>> record(len+1,vector<int>(k+1,0));
    record[0][0]=1;
    for(int i=1;i<=len;i++){
        for(int j=0;j<=k;j++){
            record[i][j]=(record[i][j]+record[i-1][j])%base;
            if(j-(capacities[i-1]-1)>=0){
                record[i][j]=(record[i][j]+record[i-1][j-(capacities[i-1]-1)])%base;
            }
        }
    }
    return record[len][k];
    }
};

思路:

这道题的核心在于数学建模,把入场安检问题建模为一个数学问题:数组中可以任选元素相加,有多少种和为K的方案。为解决这个问题,可以引入动态规划策略。record[i][j]表示截止第i个数字,所有和为j的方案数目和。

那么动态转移公式是:record[i][j]=record[i-1][j]+record[i-1][j-capacities[i-1]-1];

不要忘了除以base,防止溢出。最后返回record[len][k]。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值