1 条题解

  • 0
    @ 2025-5-12 22:43:10

    解题思路

    1. 分类顶点

      • 首先,将所有顶点(除了原点)根据其所在的象限进行分类。四个象限的定义如下:
        • 第一象限:(x > 0), (y > 0)
        • 第二象限:(x < 0), (y > 0)
        • 第三象限:(x < 0), (y < 0)
        • 第四象限:(x > 0), (y < 0)
      • 根据题目描述,多边形的顶点最多分布在三个象限中。
    2. 计算斜率

      • 对于每个象限内的顶点,计算其与原点的斜率 (k = \frac{y}{x})(注意处理 (x = 0) 的情况,但题目说明没有顶点在坐标轴上)。
      • 在每个象限内,斜率是单调递增或单调递减的。需要根据这一点对斜率进行排序。
    3. 确定斜率排序方向

      • 对于每个象限,选择一个顶点作为“起始点”,然后根据其他顶点的斜率与起始点的关系确定排序方向(递增或递减)。
      • 具体来说,可以选取象限内 (x) 或 (y) 绝对值最大的点作为起始点,然后根据其他点的斜率与起始点的斜率比较确定顺序。
    4. 连接顶点

      • 从原点出发,按照排序后的顺序依次连接顶点,确保每次转向的角度是逆时针的(即外角为正)。
      • 可以通过计算相邻边之间的叉积来判断转向方向。
    5. 具体步骤

      • 将所有顶点(除了原点)分类到对应的象限。
      • 对于每个象限,计算所有顶点的斜率,并根据单调性排序。
      • 确定每个象限内顶点的访问顺序。
      • 将所有象限的顶点按逆时针方向连接起来,形成最终的顶点序列。

    示例解析

    以示例输入为例:

    1. 顶点分类:

      • 第一象限:((60, 30)), ((80, 20)), ((90, 10))
      • 第三象限:((-30, -40)), ((-30, -50)), ((-10, -60))
      • 第四象限:((70, -50)), ((50, -60)), ((90, -20))
    2. 斜率计算与排序:

      • 第一象限:
        • 斜率:(\frac{30}{60} = 0.5), (\frac{20}{80} = 0.25), (\frac{10}{90} \approx 0.111)
        • 斜率递减,排序为 ((60, 30)), ((80, 20)), ((90, 10))
      • 第三象限:
        • 斜率:(\frac{-40}{-30} \approx 1.333), (\frac{-50}{-30} \approx 1.666), (\frac{-60}{-10} = 6)
        • 斜率递增,排序为 ((-30, -40)), ((-30, -50)), ((-10, -60))
      • 第四象限:
        • 斜率:(\frac{-50}{70} \approx -0.714), (\frac{-60}{50} = -1.2), (\frac{-20}{90} \approx -0.222)
        • 斜率递增,排序为 ((50, -60)), ((70, -50)), ((90, -20))
    3. 连接顶点:

      • 从原点出发,按照第三象限、第四象限、第一象限的顺序连接顶点(逆时针方向)。
      • 具体顺序:
        • 原点 ((0, 0))
        • 第三象限:((-30, -40)), ((-30, -50)), ((-10, -60))
        • 第四象限:((50, -60)), ((70, -50)), ((90, -20))
        • 第一象限:((90, 10)), ((80, 20)), ((60, 30))
      • 最终顺序与示例输出一致。

    代码实现(伪代码)

    #include <iostream>
    #include <cmath>
    #include <stdio.h>
    #include <algorithm>
    
    using namespace std;
    
    struct point
    {
    	double x,y;
    }p[50],pp;
    double cross(point a,point b,point c)
    {
    	return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y) ;
    }
    bool cmp(point a,point b)
    {
    	int cr = cross(a,b,pp) ;//判断顺时针还是逆时针
    	if(cr > 0) return true ;
    	else if(cr < 0) return false ;
    }
    int main()
    {
    	int cnt = 0;
    	while (scanf("%lf %lf",&p[cnt].x,&p[cnt].y) != EOF)
    	{
    		++cnt;
    	}
    	pp.x = pp.y = 0 ;
    	sort(p+1,p+cnt,cmp);
    	for (int i = 0 ; i < cnt ; i++)
    	{
    		cout<<"("<<p[i].x<<","<<p[i].y<<")"<<endl;
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    1008
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者