一、题目描述
AI识别到面板上有N(1 ≤ N ≤ 100)个指示灯,灯大小一样,任意两个之间无重叠。
由于AI识别误差,每次别到的指示灯位置可能有差异,以4个坐标值描述AI识别的指示灯的大小和位置(左上角x1,y1,右下角x2,y2),
请输出先行后列排序的指示灯的编号,排序规则:
- 每次在尚未排序的灯中挑选最高的灯作为的基准灯,
- 找出和基准灯属于同一行所有的灯进行排序。两个灯高低偏差不超过灯半径算同一行(即两个灯坐标的差 ≤ 灯高度的一半)。
二、输入描述
第一行为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、说明
五、解题思路
- 第一行输入灯的个数N;
- 接下来的N行输入灯的序号和坐标(左上角x1,y1,右下角x2,y2),比如1 1 1 3 3;
- 定义一个等的集合,将灯的序号和坐标以Light对象的形式加入其中;
- 循环灯集合lightList;
- 先行后列,找出未排序最大的灯;
- 找出同一行的灯;
- 按照先行后列进行排序;
- 输出先行后列排序的指示灯的编号。
六、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;
}
2万+

被折叠的 条评论
为什么被折叠?



