西南交通大学算法分析与设计第一次作业

1.有一个水平放置的矩形纸箱,现希望用隔板把这个纸箱分割成很多小的格子,每个格子都可以放下若干个物品。从上往下看的效果如下图所示。已知纸箱左上角和右下角的坐标以及每个隔板放入纸箱后的位置坐标。现有若干个物品,已知物品放入纸箱后的位置,求每个格子中有多少个物品?

输入描述:

   输入的第一行包含6个整数,分别是n(0<n<=5000),m(0<m<=5000),x1,y1,x2,y2,分别表示隔板的数量,物品的数量,矩形纸箱左上角点的坐标和右下角点的坐标(从上往下看投影到XY平面的坐标),其后有n行,分别表示隔板的位置,按从左到右的顺序排列,且各个隔板互不相交。每一行有两个整数,Ui和Li,表示第i个隔板的位置坐标在(Ui,y1)和(Li,y2)。其后的m行,每一行有两个整数,Xj Yj,分别表示物品的位置。物品不可能正好在隔板上,也不可能在箱子外。

输出描述:

    输出n+1行,每一行的形式为:k:h。其中k表示格子的编号,最左边的格子为0,依次递增,最右边的格子为n;h为第k个格子中物品的数量。

样例输入:

5 6 0 10 60 0

3 1

4 3

6 8

10 10

15 30

1 5

2 1

2 8

5 5

40 10

7 9

样例输出:

0: 2

1: 1

2: 1

3: 1

4: 0

5: 1


声明:本系列所有作业以及实验均只给出代码。


#include <iostream>

using namespace std;

// 物品坐标
typedef struct Point{
    int x{}, y{};
}Point;

// 边界线
typedef struct Board{
    Point up{}, low{};
    // 斜率
    float k = 0;
}Board;

/**
 * @brief 该函数采用的知识为线性规划
 *        即y > k(x - x0) + y0 || y < k(x - x0) + y0
 *        若输出true则点在板的左边,否则在右边
 */
inline bool check(Point location, Board board) {
    if (board.k == 0) {
        // 斜率为无穷的情况
        return location.x < board.up.x;
    } else if ((location.y > (board.k * (location.x - board.up.x) + board.up.y)) && (board.k > 0)) {
        return true;
    } else if ((location.y < (board.k * (location.x - board.up.x) + board.up.y)) && (board.k < 0)){
        return true;
    } else {
        return false;
    }
}

int main() {
    int n, m;
    int x1, x2, y1, y2;
    // 输入部分
    cin >> n >> m >> x1 >> y1 >> x2 >> y2;
    Point items[m];
    Board boards[n];
    int counter[n + 1];
    for (int i = 0; i < n; ++i) {
        cin >> boards[i].up.x >> boards[i].low.x;
        boards[i].up.y = y1;
        boards[i].low.y = y2;
        // 输入板坐标的同时计算板斜率
        if (boards[i].up.x == boards[i].low.x) {
            boards[i].k = 0;
        } else {
            boards[i].k = static_cast<float>(boards[i].up.y - boards[i].low.y) /
                          static_cast<float>(boards[i].up.x - boards[i].low.x);
        }
        // 初始化计数器
        counter[i] = 0;
    }
    counter[n] = 0;
    // 输入物品坐标
    for (int i = 0; i < m; ++i) {
        cin >> items[i].x >> items[i].y;
    }
    // 让每个点从左往右依次对板遍历
    // 仅在板的输入为有序的情况下有效
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            if (check(items[i], boards[j])) {
                counter[j]++;
                break;
            } else if (j == n - 1) {
                counter[n]++;
            }

        }
    }
    for (int i = 0; i < n + 1; ++i) {
        cout << i << ": " << counter[i] << endl;
    }
    return 0;
}

本算法时间复杂度为n方,仅供参考借鉴,欢迎大佬提供更快算法的思路。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jellyfish Knight

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值