力扣10.5

2187. 完成旅途的最少时间

给你一个数组time ,其中 time[i] 表示第 i 辆公交车完成 一趟旅途 所需要花费的时间。

每辆公交车可以 连续 完成多趟旅途,也就是说,一辆公交车当前旅途完成后,可以 立马开始 下一趟旅途。每辆公交车 独立 运行,也就是说可以同时有多辆公交车在运行且互不影响。

给你一个整数 totalTrips ,表示所有公交车 总共 需要完成的旅途数目。请你返回完成 至少 totalTrips 趟旅途需要花费的 最少 时间。

数据范围

  • 1 <= time.length <= 105
  • 1 <= time[i], totalTrips <= 107

分析

二分答案,存在一个时间t,在小于t的时候公交车无论如何都无法完成任务,而大于等于t的时候肯定有一种方法可以完成任务,因此只需要二分查找这个点,注意一下二分查找的写法

//查找满足条件的最小值
while(l<r){
	int mid = (l + r) >> 1;
	if(check(mid)) r = mid;
	else l = mid + 1;
}
// 满足条件的最大值
while(l < r) {
	int mid = (l + r + 1) >> 1;
	if(check(mid)) l = mid;
	else r = mid - 1;
}

可以这样记

  • l = m i d l=mid l=mid时,下一个 m i d = ( l + r + 1 ) / 2 mid=(l+r+1)/2 mid=(l+r+1)/2
  • l = m i d + 1 l=mid+1 l=mid+1时,下一个 m i d = ( l + r ) / 2 mid=(l+r)/2 mid=(l+r)/2

代码

typedef long long LL;
class Solution {
public:
    bool check(LL mid, vector<int>& time, LL totalTrips) {
        LL sum = 0;
        for(auto k : time) {
            sum += mid / k;
        }
        return sum >= totalTrips;
    }
    LL find(LL l, LL r, vector<int>& time, LL totalTrips) {
        while(l < r) {
            LL mid = (l + r) >> 1;
            if(check(mid, time, totalTrips)) r = mid;
            else l = mid + 1;
        }
        return l;
    }
    long long minimumTime(vector<int>& time, LL totalTrips) {
        LL l = 0, r = 1e14 + 5;
        LL res = find(l, r, time, totalTrips);
        return res;
    }
};

1301. 最大得分的路径数目

给你一个正方形字符数组 board ,你从数组最右下方的字符 'S' 出发。

你的目标是到达数组最左上角的字符 'E' ,数组剩余的部分为数字字符 1, 2, ..., 9 或者障碍'X'。在每一步移动中,你可以向上、向左或者左上方移动,可以移动的前提是到达的格子没有障碍。

一条路径的 「得分」 定义为:路径上所有数字的和。

请你返回一个列表,包含两个整数:第一个整数是 「得分」 的最大值,第二个整数是得到最大得分的方案数,请把结果对 10^9 + 7 取余。

如果没有任何路径可以到达终点,请返回 [0, 0]

数据范围

  • 2 <= board.length == board[i].length <= 100

分析

记忆化搜索,令dp[x][y]表示从(x,y)出发到终点的最大数字和

代码

typedef long long LL;
class Solution {
public:
    const static LL N = 105, mod = 1e9 + 7;
    int dp[N][N], cnt[N][N];
    int dx[3] = {-1, -1, 0};
    int dy[3] = {-1, 0, -1};
    bool vis[N][N];
    int n, m;
    LL dfs(int x, int y, vector<string>& board) {
        if(dp[x][y]) return dp[x][y];
        if(x == 0 && y == 0) return dp[x][y] = 0;
        auto& t = dp[x][y];
        LL maxx = 0;
        for(int i = 0; i < 3; i ++ ) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
            if(board[nx][ny] == 'X') continue;
            if(vis[nx][ny]) continue;
            vis[nx][ny] = true; 
            LL tmp = dfs(nx, ny, board);
            if(tmp > maxx) {
                maxx = tmp;
                cnt[x][y] = cnt[nx][ny];
            } else if(tmp == maxx) {
                cnt[x][y] += cnt[nx][ny];
            }
            cnt[x][y] %= mod;
            vis[nx][ny] = false;
        }
        if(cnt[x][y])
            t += maxx;
        t %= mod;
        if(board[x][y] >= '0' && board[x][y] <= '9')
            t += board[x][y] - '0';
        // cout << x << " " << y << " " << t << endl;
        return t;
    }
    vector<int> pathsWithMaxScore(vector<string>& board) {
        n = board.size();
        m = board[0].size();
        vis[n - 1][m - 1] = true;
        cnt[0][0] = 1;
        dfs(n - 1, m - 1, board);
        return {dp[n - 1][m - 1], cnt[n - 1][m - 1]};
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值