1 条题解
-
0
题意分析
本题中斯坦有 根长度不同的棍子,以随机方式扔到地板上,要找出扔完后处于最上面(即上面没有其他棍子)的棍子。输入每个案例时,先输入棍子数量 (),接着 行每行四个数字,表示一根棍子两个端点的平面坐标,且棍子按扔的顺序给出。需按扔的顺序输出处于最上面的棍子编号。
解题思路
- 数据存储与定义:定义结构体 存储点的坐标,同时定义 (实际就是 ,用于向量运算),重载减法运算符用于计算向量,定义 函数计算向量叉积。定义数组 存储棍子的端点坐标,长度为 (因为每根棍子两个端点)。
- 输入与初始化:循环读取每个案例的 ,并依次读取每根棍子两个端点的坐标存储到 数组中。初始化变量 为 0(不过在当前代码中 未实际使用)。
- 判断最上面的棍子:外层循环遍历每根棍子 (从 1 到 )。内层循环遍历其余棍子 (从 到 )。通过向量叉积判断棍子 和棍子 的位置关系,若棍子 的两个端点相对于棍子 的两个端点的向量叉积都满足一定条件(即棍子 的端点在棍子 端点所确定直线的同一侧),则说明棍子 不在棍子 上面。当内层循环完整执行完(即没有其他棍子在棍子 上面),则棍子 是处于最上面的棍子,按格式输出其编号。最后输出最后一根棍子的编号(因为最后扔的棍子肯定在最上面)。
代码解释
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N = 200010; // 定义点的结构体 struct Point { double x, y; Point(double x = 0, double y = 0) : x(x), y(y) {} }; // 定义向量(实际就是点,用于向量运算) typedef Point Vector; Point dt[N]; // 重载减法运算符,用于计算向量 Point operator-(Point a, Point b) { return Vector(a.x - b.x, a.y - b.y); } // 计算向量叉积的函数 double Cross(Vector a, Vector b) { return a.x * b.y - a.y * b.x; } int main() { int n, k, j; // 循环读取每个案例的 n,当 n 为 0 时结束输入 while (scanf("%d", &n), n) { k = 0; // 读取每根棍子两个端点的坐标存储到 dt 数组中 for (int i = 1; i <= n; i++) scanf("%lf%lf%lf%lf", &dt[i].x, &dt[i].y, &dt[i + n].x, &dt[i + n].y); // 输出提示信息 printf("Top sticks: "); // 遍历每根棍子 i for (int i = 1; i < n; i++) { // 遍历其余棍子 j for (j = i + 1; j <= n; j++) { // 通过向量叉积判断棍子 i 和棍子 j 的位置关系 if (Cross(dt[i] - dt[j], dt[i] - dt[j + n]) * Cross(dt[i + n] - dt[j], dt[i + n] - dt[j + n]) <= 0) if (Cross(dt[j] - dt[i], dt[j] - dt[i + n]) * Cross(dt[j + n] - dt[i], dt[j + n] - dt[i + n]) <= 0) break; } // 如果内层循环完整执行完,说明棍子 i 是处于最上面的棍子,输出其编号 if (j == n + 1)printf("%d, ", i); } // 输出最后一根棍子的编号(最后扔的棍子肯定在最上面) printf("%d.\n", n); } return 0; }
- 结构体与函数定义部分:定义 结构体表示点的坐标, 类型实际就是 ,重载减法运算符方便计算向量, 函数用于计算向量叉积,这些都是为后续判断棍子位置关系做准备。
- 主函数部分:通过 循环读取每个案例的 及棍子端点坐标。两层循环用于遍历棍子并判断位置关系,根据判断结果输出处于最上面的棍子编号。
复杂度分析
- 时间复杂度:输入数据部分时间复杂度为 (读取 根棍子的端点坐标)。判断最上面棍子的部分,外层循环 次,内层循环平均 次( 从 1 到 ),每次循环内的向量叉积计算是常数时间,所以这部分时间复杂度为 。整体时间复杂度为 。
- 空间复杂度:存储棍子端点坐标使用数组 ,长度为 ,所以空间复杂度为 。
注意事项
- 输入数据验证:代码中未对输入的坐标数据进行有效性验证,如坐标值的范围等,实际应用中可能需要添加验证逻辑。
- 浮点数运算:由于使用了浮点数进行向量叉积计算,可能会存在精度问题,对于一些边界情况(如非常接近平行的棍子),可能会影响判断结果。
- 1
信息
- ID
- 1653
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者