【华为练习题】 求最大凸多边形(高级)

【华为练习题】 求最大凸多边形(高级)

题目

题目描述:

给定一些点,输出最大面积的凸边形。输出起始点为x轴最左边的点,按照顺时针方向输出,每个点必须是凸边形的顶点(不输出边上或凸边形内的点)。输入第一个数n为坐标点个数,后面依次为n个坐标点的坐标,横坐标在前,不同坐标点用‘;’隔开,相同坐标点的横纵坐标用‘,’隔开。

输入样例:

13;-4,1;-2,3;1,3;2,2;1,4;5,4;6,1;2,-4;-3,-3;1,-1;-2,-2;1,-2;-1,-1

输出样例:

-4,1;-2,3;1,4;5,4;6,1;2,-4;-3,-3

注:

- 输入数据的第一个数为点的数目,然后是分号;再后面就是以分号间隔的点;

- 点的数目最少为3个,最多为65535;

- 该题目和斜率相关。

分析

从横坐标最小的点,斜率为正无限开始,依次寻找下一个坐标点。具体过程为,求出该点与其它所有点的斜率,找到小于当前斜率的前提下能形成最大斜率且横坐标大于等于该点的点。直到找到横坐标最大的点为止。再从该点,斜率为正无限开始,依次寻找下一个坐标点。具体过程为,求出该点与其它所有点的斜率,找到小于当前斜率的前提下能形成最大斜率且横坐标小于等于该点的点。直到找到初始位置为止。

解答

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

struct Point
{
    Point(int a, int b):x(a),y(b) {};
    int x,y;
};

// 判断字符是否为分隔符
inline bool isSperator(char c){
    return c == ‘,‘ || c == ‘;‘;
}

// 计算斜率
inline double computeK(Point p1, Point p2){
    double disX = p2.x - p1.x;
    double disY = p2.y - p1.y;
    if (disX == 0)
    {
        return disY > 0 ? INT_MAX : INT_MIN;
    }
    return disY / disX;
}

// 找到下一个符合条件的坐标点
int findNextPoint(const vector<Point> &vp, int now, double &nowK, bool &flag){
    if (flag)
    {
        int max = now + 1;
        double maxK = computeK(vp[now],vp[max]);
        for (unsigned i = now + 2; i < vp.size(); i++)
        {
            double k = computeK(vp[now],vp[i]);
            if (k > maxK && k <= nowK)
            {
                max = i;
                maxK = k;
            }
        }
        nowK = maxK;
        return max;
    }
    else
    {
        int max = now - 1;
        double maxK = computeK(vp[max],vp[now]);
        for (int i = now - 2; i >= 0; i--)
        {
            double k = computeK(vp[i],vp[now]);
            if (k > maxK && k <= nowK)
            {
                max = i;
                maxK = k;
            }
        }
        nowK = maxK;
        return max;
    }
}

void findPoints(const string &s, vector<Point> &result){

    // 将所有数字读入tmp中
    vector<int> tmp;
    auto begin = s.begin();
    while (begin != s.end())
    {
        if (isSperator(*begin))
        {
            begin++;
            continue;
        }
        auto ahead = begin + 1;
        while (ahead != s.end() && !isSperator(*ahead))
        {
            ahead++;
        }
        tmp.push_back(stoi(string(begin,ahead)));
        begin = ahead;
    }

    // 根据读入数据依次创建坐标点,并根据横坐标升序排序(横坐标相同则按纵坐标降序排序)
    vector<Point> vp;
    for (unsigned i = 1; i < tmp.size() - 1; i+= 2)
    {
        Point p(tmp[i],tmp[i + 1]);
        vp.push_back(p);
    }
    sort(vp.begin(),vp.end(),[](const Point &p1, const Point &p2){
        return p1.y > p2.y;
    });
    stable_sort(vp.begin(),vp.end(),[](const Point &p1, const Point &p2){
        return p1.x < p2.x;
    });

    // 顺势针依次寻找坐标点
    bool flag = true;
    double nowK = INT_MAX;
    int now = findNextPoint(vp,0,nowK,flag);
    result.push_back(vp[0]);
    while (now != 0)
    {
        if (now == vp.size() - 1)
        {
            flag = false;
            nowK = INT_MAX;
        }
        result.push_back(vp[now]);
        now = findNextPoint(vp,now,nowK,flag);
    }
}

int main()
{
    string s;
    vector<Point> result;
    cin >> s;
    findPoints(s,result);
    // 依次打印坐标点
    for (unsigned i = 0; i < result.size(); i++)
    {
        cout << result[i].x << "," << result[i].y;
        if (i != result.size()-1) cout << ";";
    }
    cout << endl;
    return 0;
}
时间: 2024-10-05 04:27:41

【华为练习题】 求最大凸多边形(高级)的相关文章

华为上机练习题--求两个数组的总和

题目: 求两个数组的和差:就是去掉两个数组中相同的元素 然后将两个数组中的元素存放在一个新的数组中,且数组A中元素要在B数组元素之前 如:输入: int[] a={1,2,4,7,6,9}; int[] b={2,4,3,10}; 输出: int[] c = {1, 7, 6, 9, 3, 10}; 分析: 剔除相同的元素要互相比较, 然后将不同的元素先后插入新的数组中, 所以我将重点放在比较上, 有可能效率有点低, 大家有什么好的想法可以分享下: 代码如下: package com.wenj.

【华为练习题】 阿姆斯特朗数(初级)

[华为练习题] 阿姆斯特朗数(初级) 题目 如果一个正整数等于其各个数字的立方和,则该数称为阿姆斯特朗数(亦称为自恋性数),1除外,如407 = 4^3+0^3+7^3就是一个阿姆斯特朗数.试编程求n(n ≤ 65536)以内的所有阿姆斯特朗数. 原型: int CalcArmstrongNumber(int n); 输入参数: int n: n ≤ 65536 返回值: n以内的阿姆斯特朗数的数量 解答 #include <iostream> using namespace std; boo

【华为练习题 】 长寿的兔子

[华为练习题 ] 长寿的兔子 题目 从前有一对长寿的兔子,他们每个月生出一对小兔子,第一个月新生产的兔子两个月就长大了,在第三个月初开始生他们的下一代小兔子,这样一代一代的生下去,不考虑兔子的寿命,求第n个月出生多少对小兔子 简单示例: 比如输入1,第一个月出生的兔子只有一对,所以输出为1 比如输入2,第二个月出生的兔子只有一对,所以输出为1 比如输出为3,则该月份有两对兔子出生,则输出为2 要求: 实现以下接口: 输入一个正整数,表示第几个月,输出该月份生产出的小兔子的对数 调用者会保证: 输

【华为练习题 】 n位水仙花数(初级)

[华为练习题 ] n位水仙花数(初级) 题目 水仙花数又称阿姆斯特朗数. 水仙花数是指一个n 位数( n≥3 ),它的每个位上的数字的n 次幂之和等于它本身.(例如:1^3 + 5^3 + 3^3 = 153) 求输入的数字是否为水仙花数 解答 #include <iostream> #include <vector> using namespace std; bool isRight(int n){ vector<int> v; int sum = 0, tmp =

华为练习题--社交好友判断

好友关系管理 描述: 现有一个社交网站,其好友推荐策略为:用户A和用户B不是好友,当二人的共同好友数量超过好友推荐阈值m时,就向A和B分别推荐为彼此好友. 本题任务为:对设定的m值,给定一组用户及各自好友列表,对这一组用户,反复自动应用上述好友推荐策略后(假设每次推荐都被采纳),求指定用户的最终好友列表. 注:好友关系是双向的,即:如果用户A是用户B的好友,那么用户B一定也是用户A的好友. 写一个程序,在社交网络中实现: 1)初始化社交网络 2)创建用户 3)增加指定两个用户之间的好友关系 4)

【华为练习题】 最后一个单词的长度(初级)

[华为练习题] 最后一个单词的长度(初级) 题目 描述: 计算字符串最后一个单词的长度,单词以空格隔开. 题目类别: 字符串 输入: 一行字符串,长度小于128. 输出: 整数N,最后一个单词的长度. 样例输入: hello world 样例输出: 5 解答 #include <iostream> #include <string> using namespace std; int last_word_length(const string &s){ auto begin

华为练习 求二叉树的宽度和深度

求二叉树的宽度和深度 给定一个二叉树,获取该二叉树的宽度和深度. 例如输入 a / \ b c / \ / \ d e f g 返回3. 详细描述: 接口说明 原型: int GetBiNodeInfo(BiNode &head, unsigned int *pulWidth, unsigned int *pulHeight) 输入参数: head 需要获取深度的二叉树头结点 输出参数(指针指向的内存区域保证有效): pulWidth 宽度 pulHeight 高度 返回值: 0 成功 1 失败

【华为练习题】字符出现频率

[华为练习题]字符出现频率 题目 描述:写出一个程序,输出基准字符串中统计指定字符出现的频率 字符串仅包括英文大小写字母和空格.逗号.点号 小数点后保留2位有效数字,第三位四舍五入 举例: 输入:wo shi, yi zhi.xiao xiao niao ' '(空格) 输出:0.17 接口说明: /* 功能: 输入的基准字符串中统计指定字符出现的频率 字符串仅包括英文大小写字母和空格.逗号.点号 小数点后保留2位有效数字,第三位四舍五入 输入: String pString 输入的基准字符串

华为测试 求小球落地5次后所经历的路程和第5次反弹的高度

假设一个球从任意高度自由落下,每次落地后反跳回原高度的一半; 再落下, 求它在第5次落地时,共经历多少米?第5次反弹多高? 输入起始高度,int型 分别输出第5次落地时,共经过多少米第5次反弹多高 [去掉小数末尾无效的0] 样例输入:1 样例输出:2.875 0.03125 #include<iostream> using namespace std; double high(double H,int N); double total(double H,int N); int main() {