双周赛5973. 价格范围内最高排名的 K 样物品

题目

给你一个下标从 0 开始的二维整数数组 grid ,它的大小为 m x n ,表示一个商店中物品的分布图。数组中的整数含义为:

0 表示无法穿越的一堵墙。
1 表示可以自由通过的一个空格子。
所有其他正整数表示该格子内的一样物品的价格。你可以自由经过这些格子。

从一个格子走到上下左右相邻格子花费 1 步。

同时给你一个整数数组 pricing 和 start ,其中 pricing = [low, high] 且 start = [row, col] ,表示你开始位置为 (row, col) ,同时你只对物品价格在 闭区间 [low, high] 之内的物品感兴趣。同时给你一个整数 k 。

你想知道给定范围 内 且 排名最高 的 k 件物品的 位置 。排名按照优先级从高到低的以下规则制定:

距离:定义为从 start 到一件物品的最短路径需要的步数(较近 距离的排名更高)。
价格:较低 价格的物品有更高优先级,但只考虑在给定范围之内的价格。
行坐标:较小 行坐标的有更高优先级。
列坐标:较小 列坐标的有更高优先级。

请你返回给定价格内排名最高的 k 件物品的坐标,将它们按照排名排序后返回。如果给定价格内少于 k 件物品,那么请将它们的坐标 全部 返回。

示例 1:
在这里插入图片描述

输入:grid = [[1,2,0,1],[1,3,0,1],[0,2,5,1]], pricing = [2,5], start = [0,0], k = 3
输出:[[0,1],[1,1],[2,1]]
解释:起点为 (0,0) 。
价格范围为 [2,5] ,我们可以选择的物品坐标为 (0,1),(1,1),(2,1) 和 (2,2) 。
这些物品的排名为:
- (0,1) 距离为 1
- (1,1) 距离为 2
- (2,1) 距离为 3
- (2,2) 距离为 4
所以,给定价格范围内排名最高的 3 件物品的坐标为 (0,1),(1,1) 和 (2,1) 。

思路

题目要求从起始位置开始向四周寻找距离短且符合要求的节点,采用BFS方法利用队列求解。
而题目的阻碍在于题目中优先级的理解:

排名按照优先级从高到低:
    距离:定义为从 start 到一件物品的最短路径需要的步数(较近 距离的排名更高)。
    价格:较低 价格的物品有更高优先级,但只考虑在给定范围之内的价格。
    行坐标:较小 行坐标的有更高优先级。
    列坐标:较小 列坐标的有更高优先级。

这句话的意思为距离越小排的越前,在距离相等的情况下价格越低排的越靠前,在距离和价格相等的情况下点的横坐标越小排的越靠前,在距离、价格和横坐标相等的情况下点的纵坐标越小排的越靠前。(因为此处不注意,爆了好多次错)
如果在筛选数组中价格时进行判断的话,比较麻烦。

因此这里我们可以通过BFS遍历筛选出价格符合的项,通过创建vector<vector < int>>ans记录其距离、价格、行坐标、 列坐标。数组遍历完成后,按照上面的优先级建立自定义排序规则,并对其进行排序,最后输出前k个。(比赛时没想到此方法)

题目本身不是很难,但是对题目理解有误,导致耽误一定时间

代码

class Solution {
public:
    vector<vector<int>> highestRankedKItems(vector<vector<int>>& grid, vector<int>& pricing, vector<int>& start, int k) {
        int dx[4] = {0,0,-1,1};
        int dy[4] = {-1,1,0,0};
        int len_r = grid.size(), len_l = grid[0].size();
        queue<vector<int>> q;
        vector<vector<int>> ans;
        if(grid[start[0]][start[1]]>=pricing[0]&&grid[start[0]][start[1]]<=pricing[1]){
            ans.push_back(start);
            grid[start[0]][start[1]]=-1;
        }
        start.push_back(0);
        q.push(start);
        vector<vector<int>> m;
        while(!q.empty()){
            vector<int> t = q.front();
            q.pop();
            for(int i=0;i<4;i++){
                int index_x = t[0]+dx[i];
                int index_y = t[1]+dy[i];
                if(index_x<0||index_x>=len_r||index_y<0||index_y>=len_l||grid[index_x][index_y]<=0)
                    continue;
                q.push({index_x, index_y, t[2]+1});
                if(grid[index_x][index_y]>=pricing[0]&&grid[index_x][index_y]<=pricing[1]){
                    m.push_back({t[2]+1, grid[index_x][index_y], index_x, index_y});
                }
                grid[index_x][index_y] = -1;
            }
        }
        sort(m.begin(), m.end(), [&](auto &a, auto &b){
            if(a[0]==b[0]){
                if(a[1]==b[1]){
                    if(a[2]==b[2]){
                        return a[3]<b[3];
                    }
                    return a[2]<b[2];
                }
                return a[1]<b[1];
            }
            return a[0]<b[0];
        });
        k = min(k-ans.size(), m.size());
        for(int i=0;i<k;i++)
            ans.push_back({m[i][2], m[i][3]});
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值