列表

详情


NC308. 过河

描述

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。

题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

其中正整数 l ,表示独木桥的长度。s,t,分别表示青蛙一次跳跃的最小距离,最大距离,数组 nums 中 m 个不同的正整数分别表示这 m 个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。

数据范围:

示例1

输入:

10,2,3,[2,3,5,6,7]

输出:

2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 3ms, 内存消耗: 556KB, 提交时间: 2022-06-18

class Solution {
public:
    int crossRiver(int l, int s, int t, vector<int>& nums) {
        int before = 0,lst=0,end;
        int dp[20005];
        int rock[20005];
        sort(nums.begin(),nums.end());            
        memset(rock,0, sizeof(rock));
        memset(dp,-1, sizeof(dp));
        dp[0]=0;
        for(int num:nums)
            if(num<l){
                if((num-before)>2*s*t)
                {//printf("%d ",((num-before)%(s*t)+s*t)%9);
                 lst=(num-before)%(s*t)+s*t+lst;}
                else
                {//printf("%d ",((num-before)+lst)%9);
                 lst=(num-before)+lst;}
                rock[lst]=1;
                
                
                before=num;
            }else break;
        
         if((l-before)>2*s*t)
             end=(l-before)%(s*t)+s*t+lst;
         else
             l=(l-before)+l;
        for(int i=0;i<=end+t;i++){
            
            int mn=105;
            for(int j=s;j<=t;j++)
                if(i-j>=0&&dp[i-j]>-1) mn=min(dp[i-j]+rock[i],mn);
            if(mn!=105) dp[i] = mn;
        }
        int res=105;
        for(int i=end;i<end+t;i++)
            if(dp[i]>=0)res=min(res,dp[i]);
        return res;
    }
};

C++ 解法, 执行用时: 3ms, 内存消耗: 560KB, 提交时间: 2022-03-14

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param l int整型 
     * @param s int整型 
     * @param t int整型 
     * @param nums int整型vector 
     * @return int整型
     */
    
    int crossRiver(int l, int s, int t, vector<int>& nums) {
        // write code her
        int before = 0,lst=0,end;
        int dp[20005];
        int rock[20005];
        sort(nums.begin(),nums.end());
            
        memset(rock,0, sizeof(rock));
        memset(dp,-1, sizeof(dp));
        dp[0]=0;
        for(int num:nums)
            if(num<l){
                if((num-before)>2*s*t)
                {//printf("%d ",((num-before)%(s*t)+s*t)%9);
                 lst=(num-before)%(s*t)+s*t+lst;}
                else
                {//printf("%d ",((num-before)+lst)%9);
                 lst=(num-before)+lst;}
                rock[lst]=1;
                
                
                before=num;
            }else break;
        
         if((l-before)>2*s*t)
             end=(l-before)%(s*t)+s*t+lst;
         else
             l=(l-before)+l;
        for(int i=0;i<=end+t;i++){
            
            int mn=105;
            for(int j=s;j<=t;j++)
                if(i-j>=0&&dp[i-j]>-1) mn=min(dp[i-j]+rock[i],mn);
            if(mn!=105) dp[i] = mn;
            //printf("%d ",dp[i]);
        }
        int res=105;
        for(int i=end;i<end+t;i++)
            if(dp[i]>=0)res=min(res,dp[i]);
        return res;
    }
};

C++ 解法, 执行用时: 4ms, 内存消耗: 432KB, 提交时间: 2022-07-13

class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param l int整型
     * @param s int整型
     * @param t int整型
     * @param nums int整型vector
     * @return int整型
     */
    int crossRiver(int L, int S, int T, vector<int>& nums) {
        // write code here
        int M = nums.size();
        sort(nums.begin(), nums.end());

        if (S == T) {
            int cnt = 0;
            for (int i = 0; i < M; i++) {
                if (nums[i] % S == 0) {
                    cnt++;
                }
            }
            return cnt;
        }

        int river[10010];
        for (int i = 0; i < 10010; i++) {
            river[i] = 0;
        }
        int dist = 0;
        for (int i = 0, last = 0; i < M; i++) {
            if (nums[i] - last > 100) {
                dist += 100;
            } else {
                dist += nums[i] - last;
            }
            last = nums[i];
            river[dist] = 1;
        }

        int f[10010];
        f[0] = 0;
        for (int i = 1; i <= dist + 10; i++) {
            f[i] = 1e9;
            for (int j = S; j <= T; j++) {
                if (i - j >= 0) {
                    f[i] = min(f[i], f[i - j] + river[i]);
                }
            }
        }

        int res = 1e9;
        for (int i = dist + 1; i <= dist + 10; i++) {
            res = min(res, f[i]);
        }
        return res;
    }
};

C++ 解法, 执行用时: 4ms, 内存消耗: 456KB, 提交时间: 2022-07-03

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param l int整型 
     * @param s int整型 
     * @param t int整型 
     * @param nums int整型vector 
     * @return int整型
     */
    int res = INT_MAX;
    unordered_set<int> destset;
    int end = 0;
    int crossRiver(int l, int s, int t, vector<int>& nums) {
        // write code here
        if(s == t){
            int step = 0;
            for(auto n : nums){
                if( n % t == 0) step ++;
            }
            return step;
        }
        sort(nums.begin(), nums.end());
        end = nums.back();
//         vector<int> dp(end + t + 1);
        int* dp;
        if(l > 2519){
            l = 2521;
            dp = new int[2521];
            for (auto num : nums) {
                dp[num % 2520] = 1;
            }
        }else{
            dp = new int[++l];
            for (auto num : nums) {
                dp[num] = 1;
            }
        }
        
        dp[0] = (nums[0] == 0 ? 1 : 0);
//         if(t == 1) dp[1] = 1;
//         else dp[1] = 0;
        for(int i = 1 ; i < s; i ++) dp[i] = INT_MAX;
        
        for(int i = s; i <= end + t && i <= l; i ++){
            int mn = INT_MAX;
            for(int j = s; j <= t; j ++){
                if(i - j >= 0){
                    mn = min(mn, dp[i - j]);
                }                      
            }
            dp[i] += mn;
//             else dp[i] = mn;
        }
//         for(int i = end; i < end+t && i <= l;i++)
//             if(dp[i]!= INT_MAX) res=min(res,dp[i]);
        return dp[--l];
//         return dp[l];
    }
    
//     void findMinStep(int l, int s, int t, int curl, int step){
//         if(curl > end) {
//             res = min(res, step);
//             return;
//         }
//         if(set.count(curl)) step ++;
//         for(int i = s; i <= t; i ++){
//             findMinStep(l, s, t, curl + i, step);
//         }
//     }
};

C 解法, 执行用时: 4ms, 内存消耗: 468KB, 提交时间: 2022-06-23

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param l int整型 
 * @param s int整型 
 * @param t int整型 
 * @param nums int整型一维数组 
 * @param numsLen int nums数组长度
 * @return int整型
 *
 * C语言声明定义全局变量请加上static,防止重复定义
 */
void quickSort(int *nums, int start, int end) {
    if (start < end) {
        int rIndex = rand() % (end - start + 1) + start, tmp;
        tmp = nums[rIndex];
        nums[rIndex] = nums[start];
        nums[start] = tmp;
        
        int target = nums[start], i = start, j = end;
        while(i < j) {
            while(i < j && nums[j] > target) {
                j--;
            }
            if(i < j) {
                nums[i++] = nums[j];
            }
            while(i < j && nums[i] <= target) {
                i++;
            }
            if(i < j) {
                nums[j--] = nums[i];
            }
        }
        nums[i] = target;
        
        quickSort(nums, start, i - 1);
        quickSort(nums, i + 1, end);
    }
}

int min(int a, int b) {
    return a > b ? b : a;
}

int crossRiver(int l, int s, int t, int* nums, int numsLen ) {
    quickSort(nums, 0, numsLen - 1);
    
    if (s == t) {
        int count = 0;
        for (int i = 0; i < numsLen; i++) {
            if (nums[i] % s == 0) {
                count++;
            }
        }
        
        return count;
    } else {
        int lastNIndex = 0;

        int *dp = (int *)malloc(sizeof(int) * 10000); //(2 * t + 1)
        int j = 0, minDP, len = 10000;
        dp[0] = 0;

        int k = s * t, d = 0, x;
        if (nums[0] > k) {
            d = nums[0] - k;
            nums[0] -= d;
        }
        for (int i = 1; i < numsLen; i++) {
            x = nums[i] - d - nums[i - 1];
            if (x > k) {
                d += (x - k);
            }
            nums[i] -= d; 
        }

        x = l - d - nums[numsLen - 1];
        if (x > k) {
            d += (x - k);
        }
        l -= d;

        for (int i = 1; i < s; i++) {
            if (lastNIndex != numsLen && nums[lastNIndex] == i) {
                lastNIndex++;
            }
            dp[i] = 101;
        }
        for (int i = s; i <= t; i++) {
            if (lastNIndex != numsLen && nums[lastNIndex] == i) {
                lastNIndex++;
                dp[i] = 1;
            } else {
                dp[i] = 0;
            }
        }

        for (int i = t + 1; i <= (l + t - 1); i++) {
            minDP = 101;
            for (j = t; j >= s; j--) {
                minDP = min(minDP, dp[(i-j)%len]);
            }
            if (lastNIndex != numsLen && nums[lastNIndex] == i) {
                lastNIndex++;
                dp[i%len] = minDP + 1;
            } else {
                dp[i%len] = minDP;
            }
        }

        minDP = 101;
        for (int i = l; i <= (l + t - 1); i++) {
            minDP = min(minDP, dp[i%len]);
        }

        free(dp);
        
        return minDP;
    }
}




上一题