力扣 每日一题 1326. 灌溉花园的最少水龙头数目【难度:困难,rating: 1885】(动态规划)

题目链接

https://leetcode.cn/problems/minimum-number-of-taps-to-open-to-water-a-garden/

题目来源于:第172场周赛 Q4 rating: 1885

思路

得到所有区间,按左端点L、右端点R进行排序。然后遍历这些区间覆盖的每个点i,保证L<=i<=R,设dp[i]是覆盖[0,i]的线段最小个数,则有状态转移方程 d p [ i ] = m i n ( d p [ i ] , d p [ L ] + 1 ) dp[i]=min(dp[i],dp[L]+1) dp[i]=min(dp[i],dp[L]+1)
初始化dp=inf表示不可到达,遍历排序的区间保证 i 位置能从前一个 L 位置正确转移,如果发现dp[L]=inf则说明无法转移(接不上前面区间有断层)直接返回-1。

代码

class Solution {
    static const int N=10110,inf=0x3f3f3f3f;
    int dp[N]; // 覆盖[0,i]的线段最小个数
    vector<pair<int,int>> segments; // 线段
public:
    int minTaps(int n, vector<int>& ranges) {
        for(int i=0;i<ranges.size();i++){
            if(ranges[i]==0)continue; // 单个点无用
            int x=max(0,i-ranges[i]);
            int y=min(n,i+ranges[i]);
            segments.push_back(make_pair(x,y));
        }
        sort(segments.begin(),segments.end());
        memset(dp,inf,sizeof(dp));
        dp[0]=0; // 注意初始化坐标0!
        for(auto &[l,r]:segments){ // 每次加一个区间进来
            for(int i=l;i<=r;i++){ // 遍历更新这个区间内的所有dp值
                if(dp[l]==inf){
                    return -1;
                }
                dp[i]=min(dp[i],dp[l]+1);
            }
        }
        return dp[n]==inf?-1:dp[n];
    }
};
/*
7
[1,2,1,0,2,1,0,1]
ans: 3
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nefu-ljw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值