华为OD机试真题 - AI控制面板 - 2024 E卷(Java、Python、JavaScript、C、C++合集)

一、题目描述

AI识别到面板上有N(1 ≤ N ≤ 100)个指示灯,灯大小一样,任意两个之间无重叠。

由于AI识别误差,每次别到的指示灯位置可能有差异,以4个坐标值描述AI识别的指示灯的大小和位置(左上角x1,y1,右下角x2,y2),

请输出先行后列排序的指示灯的编号,排序规则:

  1. 每次在尚未排序的灯中挑选最高的灯作为的基准灯,
  2. 找出和基准灯属于同一行所有的灯进行排序。两个灯高低偏差不超过灯半径算同一行(即两个灯坐标的差 ≤ 灯高度的一半)。

二、输入描述

第一行为N,表示灯的个数
接下来N行,每行为1个灯的坐标信息,格式为:编号 x1 y1 2 y2

  • 编号全局唯一
  • 1 ≤ 编号 ≤ 100
  • 0 ≤ x1 < x2 ≤ 1000
  • 0 ≤ y1 < y2 ≤ 1000

三、输出描述

排序后的编号列表,编号之间以空格分隔。

四、测试用例

测试用例1

1、输入

3
1 1 1 3 3
2 4 1 6 3
3 7 1 9 3

2、输出

1 2 3

测试用例2

1、输入

4
1 1 1 3 3
2 4 2 6 4
3 7 1 9 3
4 10 2 12 4

2、输出

1 2 3 4

3、说明

五、解题思路

  1. 第一行输入灯的个数N;
  2. 接下来的N行输入灯的序号和坐标(左上角x1,y1,右下角x2,y2),比如1 1 1 3 3;
  3. 定义一个等的集合,将灯的序号和坐标以Light对象的形式加入其中;
  4. 循环灯集合lightList;
    • 先行后列,找出未排序最大的灯;
    • 找出同一行的灯;
    • 按照先行后列进行排序;
  5. 输出先行后列排序的指示灯的编号。

六、Java算法源码

public class OdTest01 {
    static List<Light> lightList = new ArrayList<>(); // 存储所有灯的列表

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = Integer.parseInt(sc.nextLine()); // 读取灯的个数
        for (int i = 0; i < N; i++) {
            int[] nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
            int id = nums[0]; // 灯的编号
            int x1 = nums[1]; // 左上角 x 坐标
            int y1 = nums[2]; // 左上角 y 坐标
            int x2 = nums[3]; // 右下角 x 坐标
            int y2 = nums[4]; // 右下角 y 坐标
            Light light = new Light(id, x1, y1, x2, y2); // 创建灯对象
            lightList.add(light); // 将灯添加到列表中
        }

        List<Integer> result = new ArrayList<>(); // 存储排序后的结果
        while (!lightList.isEmpty()) {
            Light maxLight = getMaxLight(); // 获取当前最高的灯
            result.add(maxLight.id); // 将最高灯的编号加入结果
            List<Light> sameLineLights = getSameLineLights(maxLight); // 获取与最高灯同一行的灯
            sameLineLights.sort(Comparator.comparingInt(l -> l.x1)); // 按 x1 坐标排序
            for (Light l : sameLineLights) {
                result.add(l.id); // 将同一行的灯编号加入结果
            }
        }

        // 输出结果
        for (int i = 0; i < result.size(); i++) {
            if (i > 0) {
                System.out.print(" ");
            }
            System.out.print(result.get(i));
        }
    }

    // 获取当前未排序的最高灯
    public static Light getMaxLight() {
        Light light = null;
        for (Light lt : lightList) {
            if (light == null || lt.y1 < light.y1 || (lt.y1 == light.y1 && lt.x1 < light.x1)) {
                light = lt; // 选择 y1 最小(最高)的灯
            }
        }
        lightList.remove(light); // 从列表中移除已选择的灯
        return light;
    }

    // 获取与基准灯同一行的灯
    public static List<Light> getSameLineLights(Light light) {
        List<Light> lights = new ArrayList<>();
        double radius = (light.y2 - light.y1) / 2.0; // 计算灯高度的一半
        for (Light lt : lightList) {
            if (Math.abs(lt.y1 - light.y1) <= radius) { // 判断是否在同一行
                lights.add(lt);
            }
        }
        lightList.removeAll(lights); // 从列表中移除已选择的灯
        return lights;
    }

    // 灯的数据结构
    static class Light {
        int id, x1, y1, x2, y2;

        public Light(int id, int x1, int y1, int x2, int y2) {
            this.id = id;
            this.x1 = x1;
            this.y1 = y1;
            this.x2 = x2;
            this.y2 = y2;
        }
    }
}

七、Python算法源码

class Light:
    def __init__(self, id, x1, y1, x2, y2):
        self.id = id  # 灯的编号
        self.x1 = x1  # 左上角 x 坐标
        self.y1 = y1  # 左上角 y 坐标
        self.x2 = x2  # 右下角 x 坐标
        self.y2 = y2  # 右下角 y 坐标

def get_max_light(light_list):
    light = None
    for lt in light_list:
        if light is None or lt.y1 < light.y1 or (lt.y1 == light.y1 and lt.x1 < light.x1):
            light = lt  # 选择 y1 最小(最高)的灯
    light_list.remove(light)  # 从列表中移除已选择的灯
    return light

def get_same_line_lights(light, light_list):
    lights = []
    radius = (light.y2 - light.y1) / 2.0  # 计算灯高度的一半
    for lt in light_list:
        if abs(lt.y1 - light.y1) <= radius:  # 判断是否在同一行
            lights.append(lt)
    for lt in lights:
        light_list.remove(lt)  # 从列表中移除已选择的灯
    return lights

def main():
    N = int(input())  # 读取灯的个数
    light_list = []
    for _ in range(N):
        id, x1, y1, x2, y2 = map(int, input().split())
        light_list.append(Light(id, x1, y1, x2, y2))  # 创建灯对象并添加到列表

    result = []
    while light_list:
        max_light = get_max_light(light_list)  # 获取当前最高的灯
        result.append(max_light.id)  # 将最高灯的编号加入结果
        same_line_lights = get_same_line_lights(max_light, light_list)  # 获取与最高灯同一行的灯
        same_line_lights.sort(key=lambda l: l.x1)  # 按 x1 坐标排序
        for l in same_line_lights:
            result.append(l.id)  # 将同一行的灯编号加入结果

    print(" ".join(map(str, result)))  # 输出结果

if __name__ == "__main__":
    main()

八、JavaScript算法源码

class Light {
    constructor(id, x1, y1, x2, y2) {
        this.id = id;  // 灯的编号
        this.x1 = x1;  // 左上角 x 坐标
        this.y1 = y1;  // 左上角 y 坐标
        this.x2 = x2;  // 右下角 x 坐标
        this.y2 = y2;  // 右下角 y 坐标
    }
}

function getMaxLight(lightList) {
    let light = null;
    for (let lt of lightList) {
        if (light === null || lt.y1 < light.y1 || (lt.y1 === light.y1 && lt.x1 < light.x1)) {
            light = lt;  // 选择 y1 最小(最高)的灯
        }
    }
    lightList.splice(lightList.indexOf(light), 1);  // 从列表中移除已选择的灯
    return light;
}

function getSameLineLights(light, lightList) {
    let lights = [];
    let radius = (light.y2 - light.y1) / 2.0;  // 计算灯高度的一半
    for (let lt of lightList) {
        if (Math.abs(lt.y1 - light.y1) <= radius) {  // 判断是否在同一行
            lights.push(lt);
        }
    }
    for (let lt of lights) {
        lightList.splice(lightList.indexOf(lt), 1);  // 从列表中移除已选择的灯
    }
    return lights;
}

function main() {
    const readline = require('readline');
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    let N;
    let lightList = [];
    let lineCount = 0;

    rl.on('line', (line) => {
        if (lineCount === 0) {
            N = parseInt(line);  // 读取灯的个数
            lineCount++;
        } else {
            let [id, x1, y1, x2, y2] = line.split(' ').map(Number);
            lightList.push(new Light(id, x1, y1, x2, y2));  // 创建灯对象并添加到列表
            if (lightList.length === N) {
                rl.close();
            }
        }
    });

    rl.on('close', () => {
        let result = [];
        while (lightList.length > 0) {
            let maxLight = getMaxLight(lightList);  // 获取当前最高的灯
            result.push(maxLight.id);  // 将最高灯的编号加入结果
            let sameLineLights = getSameLineLights(maxLight, lightList);  // 获取与最高灯同一行的灯
            sameLineLights.sort((a, b) => a.x1 - b.x1);  // 按 x1 坐标排序
            for (let l of sameLineLights) {
                result.push(l.id);  // 将同一行的灯编号加入结果
            }
        }
        console.log(result.join(' '));  // 输出结果
    });
}

main();

九、C算法源码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct {
    int id, x1, y1, x2, y2;
} Light;

Light* getMaxLight(Light** lightList, int* size) {
    Light* light = NULL;
    for (int i = 0; i < *size; i++) {
        if (light == NULL || lightList[i]->y1 < light->y1 || 
            (lightList[i]->y1 == light->y1 && lightList[i]->x1 < light->x1)) {
            light = lightList[i];  // 选择 y1 最小(最高)的灯
        }
    }
    for (int i = 0; i < *size; i++) {
        if (lightList[i] == light) {
            for (int j = i; j < *size - 1; j++) {
                lightList[j] = lightList[j + 1];  // 从列表中移除已选择的灯
            }
            (*size)--;
            break;
        }
    }
    return light;
}

Light** getSameLineLights(Light* light, Light** lightList, int* size, int* newSize) {
    Light** lights = (Light**)malloc(*size * sizeof(Light*));
    *newSize = 0;
    double radius = (light->y2 - light->y1) / 2.0;  // 计算灯高度的一半
    for (int i = 0; i < *size; i++) {
        if (fabs(lightList[i]->y1 - light->y1) <= radius) {  // 判断是否在同一行
            lights[(*newSize)++] = lightList[i];
        }
    }
    for (int i = 0; i < *newSize; i++) {
        for (int j = 0; j < *size; j++) {
            if (lightList[j] == lights[i]) {
                for (int k = j; k < *size - 1; k++) {
                    lightList[k] = lightList[k + 1];  // 从列表中移除已选择的灯
                }
                (*size)--;
                j--;
                break;
            }
        }
    }
    return lights;
}

int compare(const void* a, const void* b) {
    Light* lightA = *(Light**)a;
    Light* lightB = *(Light**)b;
    return lightA->x1 - lightB->x1;  // 按 x1 坐标排序
}

int main() {
    int N;
    scanf("%d", &N);  // 读取灯的个数
    Light** lightList = (Light**)malloc(N * sizeof(Light*));
    for (int i = 0; i < N; i++) {
        lightList[i] = (Light*)malloc(sizeof(Light));
        scanf("%d %d %d %d %d", &lightList[i]->id, &lightList[i]->x1, 
              &lightList[i]->y1, &lightList[i]->x2, &lightList[i]->y2);  // 创建灯对象
    }

    int size = N;
    int result[100];
    int resultSize = 0;

    while (size > 0) {
        Light* maxLight = getMaxLight(lightList, &size);  // 获取当前最高的灯
        result[resultSize++] = maxLight->id;  // 将最高灯的编号加入结果
        int newSize;
        Light** sameLineLights = getSameLineLights(maxLight, lightList, &size, &newSize);  // 获取与最高灯同一行的灯
        qsort(sameLineLights, newSize, sizeof(Light*), compare);  // 按 x1 坐标排序
        for (int i = 0; i < newSize; i++) {
            result[resultSize++] = sameLineLights[i]->id;  // 将同一行的灯编号加入结果
        }
        free(sameLineLights);
    }

    for (int i = 0; i < resultSize; i++) {
        if (i > 0) {
            printf(" ");
        }
        printf("%d", result[i]);  // 输出结果
    }
    printf("\n");

    for (int i = 0; i < N; i++) {
        free(lightList[i]);
    }
    free(lightList);

    return 0;
}

十、C++算法源码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct Light {
    int id, x1, y1, x2, y2;
    Light(int id, int x1, int y1, int x2, int y2) : id(id), x1(x1), y1(y1), x2(x2), y2(y2) {}
};

Light* getMaxLight(vector<Light*>& lightList) {
    Light* light = nullptr;
    for (auto lt : lightList) {
        if (light == nullptr || lt->y1 < light->y1 || (lt->y1 == light->y1 && lt->x1 < light->x1)) {
            light = lt;  // 选择 y1 最小(最高)的灯
        }
    }
    lightList.erase(remove(lightList.begin(), lightList.end(), light), lightList.end());  // 从列表中移除已选择的灯
    return light;
}

vector<Light*> getSameLineLights(Light* light, vector<Light*>& lightList) {
    vector<Light*> lights;
    double radius = (light->y2 - light->y1) / 2.0;  // 计算灯高度的一半
    for (auto lt : lightList) {
        if (abs(lt->y1 - light->y1) <= radius) {  // 判断是否在同一行
            lights.push_back(lt);
        }
    }
    for (auto lt : lights) {
        lightList.erase(remove(lightList.begin(), lightList.end(), lt), lightList.end());  // 从列表中移除已选择的灯
    }
    return lights;
}

int main() {
    int N;
    cin >> N;  // 读取灯的个数
    vector<Light*> lightList;
    for (int i = 0; i < N; i++) {
        int id, x1, y1, x2, y2;
        cin >> id >> x1 >> y1 >> x2 >> y2;
        lightList.push_back(new Light(id, x1, y1, x2, y2));  // 创建灯对象并添加到列表
    }

    vector<int> result;
    while (!lightList.empty()) {
        Light* maxLight = getMaxLight(lightList);  // 获取当前最高的灯
        result.push_back(maxLight->id);  // 将最高灯的编号加入结果
        vector<Light*> sameLineLights = getSameLineLights(maxLight, lightList);  // 获取与最高灯同一行的灯
        sort(sameLineLights.begin(), sameLineLights.end(), [](Light* a, Light* b) {
            return a->x1 < b->x1;  // 按 x1 坐标排序
        });
        for (auto l : sameLineLights) {
            result.push_back(l->id);  // 将同一行的灯编号加入结果
        }
    }

    for (int i = 0; i < result.size(); i++) {
        if (i > 0) {
            cout << " ";
        }
        cout << result[i];  // 输出结果
    }
    cout << endl;

    for (auto lt : lightList) {
        delete lt;
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值