(B卷,100分)- AI面板识别(Java & JS & Python & C)

题目描述

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

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

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

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

输入描述

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

编号 x1 y1 x2 y2

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

输出描述

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

用例

输入 5
1 0 0 2 2
2 6 1 8 3
3 3 2 5 4
5 5 4 7 6
4 0 4 2 6
输出 1 2 3 4 5
说明

题目解析

题目给的图好像有问题,我画出来是

按照题目意思,每次取出一个最高的灯(y坐标最小的),然后找出和最高灯坐标相差小于等于灯半径的,作为同一行,然后按照x轴坐标进行升序

即存在如下用圈框住的三行,因此打印顺序是:1,2,3,4,5

Java算法源码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.StringJoiner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    int n = sc.nextInt();

    Light[] lights = new Light[n];
    for (int i = 0; i < n; i++) {
      int id = sc.nextInt();
      int x1 = sc.nextInt();
      int y1 = sc.nextInt();
      int x2 = sc.nextInt();
      int y2 = sc.nextInt();
      lights[i] = new Light(id, (x1 + x2) / 2, (y1 + y2) / 2, (x2 - x1) / 2);
    }

    System.out.println(getResult(lights));
  }

  public static String getResult(Light[] lights) {
    // 按照圆心y坐标升序
    Arrays.sort(lights, (a, b) -> a.y - b.y);

    // ans记录题解
    StringJoiner ans = new StringJoiner(" ");

    // sameRowLights记录同一行的灯
    ArrayList<Light> sameRowLights = new ArrayList<>();
    Light base = lights[0];
    sameRowLights.add(base);

    for (int i = 1; i < lights.length; i++) {
      Light light = lights[i];

      // 如果lights[i]的纵坐标和base的纵坐标相差不超过半径,则视为同一行
      if (light.y - base.y <= base.r) {
        sameRowLights.add(light);
      } else {
        // 否则,不是同一行
        // 针对同一行的灯,再按照横坐标升序
        sameRowLights.sort((a, b) -> a.x - b.x);
        sameRowLights.forEach(a -> ans.add(a.id + ""));
        sameRowLights.clear();

        // 开始新的一行记录
        base = light;
        sameRowLights.add(base);
      }
    }

    // 注意不要漏了最后一行
    if (sameRowLights.size() > 0) {
      sameRowLights.sort((a, b) -> a.x - b.x);
      sameRowLights.forEach(a -> ans.add(a.id + ""));
    }

    return ans.toString();
  }
}

class Light {
  int id; // 编号
  int x; // 圆心横坐标
  int y; // 圆心纵坐标
  int r; // 圆半径

  public Light(int id, int x, int y, int r) {
    this.id = id;
    this.x = x;
    this.y = y;
    this.r = r;
  }
}

JS算法源码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

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

const lines = [];
let n;
rl.on("line", (line) => {
  lines.push(line);

  if (lines.length === 1) {
    n = lines[0] - 0;
  }

  if (n && lines.length == n + 1) {
    lines.shift();

    const lights = lines.map((line) => {
      const [id, x1, y1, x2, y2] = line.split(" ").map(Number);
      return new Light(id, (x1 + x2) >> 1, (y1 + y2) >> 1, (x2 - x1) >> 1);
    });

    console.log(getResult(lights));

    lines.length = 0;
  }
});

class Light {
  constructor(id, x, y, r) {
    this.id = id; // 编号
    this.x = x; // 圆心横坐标
    this.y = y; // 圆心纵坐标
    this.r = r; // 圆半径
  }
}

function getResult(lights) {
  // 按照圆心y坐标升序
  lights.sort((a, b) => a.y - b.y);

  // ans记录题解
  const ans = [];

  // sameRowLights记录同一行的灯
  const sameRowLights = [];
  let base = lights[0];
  sameRowLights.push(base);

  for (let i = 1; i < lights.length; i++) {
    const light = lights[i];

    // 如果lights[i]的纵坐标和base的纵坐标相差不超过半径,则视为同一行
    if (light.y - base.y <= base.r) {
      sameRowLights.push(light);
    } else {
      // 否则,不是同一行
      // 针对同一行的灯,再按照横坐标升序
      sameRowLights.sort((a, b) => a.x - b.x).forEach((a) => ans.push(a.id));
      sameRowLights.length = 0;

      // 开始新的一行记录
      base = light;
      sameRowLights.push(base);
    }
  }

  // 注意不要漏了最后一行
  if (sameRowLights.length > 0) {
    sameRowLights.sort((a, b) => a.x - b.x).forEach((a) => ans.push(a.id));
    sameRowLights.length = 0;
  }

  return ans.join(" ");
}

Python算法源码

class Light:
    def __init__(self, id, x, y, r):
        self.id = id  # 编号
        self.x = x  # 圆心横坐标
        self.y = y  # 圆心纵坐标
        self.r = r  # 圆半径


# 输入获取
n = int(input())
arr = [list(map(int, input().split())) for _ in range(n)]
lights = list(map(lambda ele: Light(ele[0], (ele[1] + ele[3]) // 2, (ele[2] + ele[4]) // 2, (ele[3] - ele[1]) // 2), arr))


# 算法入口
def getResult():
    # 按照圆心y坐标升序
    lights.sort(key=lambda l: l.y)

    # ans记录题解
    ans = []

    # sameRowLights记录同一行的灯
    sameRowLights = []
    base = lights[0]
    sameRowLights.append(base)

    for i in range(1, len(lights)):
        light = lights[i]

        # 如果lights[i]的纵坐标和base的纵坐标相差不超过半径,则视为同一行
        if light.y - base.y <= base.r:
            sameRowLights.append(light)
        else:
            # 否则,不是同一行
            # 针对同一行的灯,再按照横坐标升序
            sameRowLights.sort(key=lambda l: l.x)
            for l in sameRowLights:
                ans.append(l.id)
            sameRowLights.clear()

            # 开始新的一行记录
            base = light
            sameRowLights.append(base)

    # 注意不要漏了最后一行
    if len(sameRowLights) > 0:
        sameRowLights.sort(key=lambda l: l.x)
        for l in sameRowLights:
            ans.append(l.id)

    return " ".join(map(str, ans))


# 算法调用
print(getResult())

C算法源码

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

#define MAX_SIZE 100

// 灯信息结构体
typedef struct {
    int id; // 灯id
    int x; // 灯的横坐标
    int y; // 灯的纵坐标
    int r; // 灯的半径
} Light;

// 记录题解
char res[100000];

int cmp(const void *a, const void *b) {
    // 按照灯的圆心y坐标升序
    return ((Light *) a)->y - ((Light *) b)->y;
}

int cmp2(const void *a, const void *b) {
    // 针对同一行的灯,按照圆心x坐标升序
    return ((Light *) a)->x - ((Light *) b)->x;
}

void joinToRes(Light sameRowLights[], int sameRowLights_size) {
    qsort(sameRowLights, sameRowLights_size, sizeof(Light), cmp2);

    for (int j = 0; j < sameRowLights_size; j++) {
        char tmp[100];
        sprintf(tmp, "%d", sameRowLights[j].id);
        strcat(res, tmp);
        strcat(res, " ");
    }
}

int main() {
    // 灯的个数
    int n;
    scanf("%d", &n);

    Light lights[MAX_SIZE];
    for (int i = 0; i < n; i++) {
        // 灯编号,以及坐标信息
        int id, x1, y1, x2, y2;
        scanf("%d %d %d %d %d", &id, &x1, &y1, &x2, &y2);

        lights[i].id = id;
        lights[i].x = (x1 + x2) / 2;
        lights[i].y = (y1 + y2) / 2;
        lights[i].r = (x2 - x1) / 2;
    }

    // 同一行的灯集合
    Light sameRowLights[MAX_SIZE];
    int sameRowLights_size = 0;

    // 按照圆心y坐标升序
    qsort(lights, n, sizeof(Light), cmp);

    // sameRowLights记录同一行的灯
    Light base = lights[0];
    sameRowLights[sameRowLights_size++] = base;

    for (int i = 1; i < n; i++) {
        Light light = lights[i];

        // 如果lights[i]的纵坐标和base的纵坐标相差不超过半径,则视为同一行
        if (light.y - base.y <= base.r) {
            sameRowLights[sameRowLights_size++] = light;
        } else {
            // 否则,不是同一行
            // 针对同一行的灯,再按照横坐标升序
            joinToRes(sameRowLights, sameRowLights_size);

            // 开始新的一行记录
            sameRowLights_size = 0;
            base = light;
            sameRowLights[sameRowLights_size++] = base;
        }
    }

    // 注意不要漏了最后一行
    if (sameRowLights_size > 0) {
        joinToRes(sameRowLights, sameRowLights_size);
    }

    // joinToRes中会在res最后多拼接一个空格,这里去掉
    res[strlen(res) - 1] = '';

    puts(res);

    return 0;
}



免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?