算法题之最大凸多边形

2.输出起始点为x轴最左边的点,

3.按照顺时针方向输出,

4.每个点必须是凸边形的顶点(不输出边上或凸边形内的点)。


输入样例: 3;1,2;2,2;3,3    输出样例: 1,2;3,3;2,2


注: - 输入数据的第一个数为点的数目,然后是分号;再后面就是以分号间隔的点; 点的数目最少为3个,最多为65535;该题目和斜率相关。

与其说这道题跟斜率有关,不如说是更二维向量,也就直线方向有关,用于判断依次连接直线时的下一个点的选择。所以要对不同方向直线进行量化。

思路记录:

 1.一堆点,从最左边最下边的点开始连线。从第一个点开始,被连接的下一个点的判断方法决定了最终的多边形是否符合要求。

2.如何判断下一个被连接的点?每一次连接后得到的直线无非在四个象限(以原点为起始点),如下图。对曲线方向进行量化。选择下一个点的条件是:每一次连接后必须使得新的直线的方向量化值比前一条直线更大;在满足前一条基础上,方向量化值又要最小。

3.直线方向量化方式是,不管用什么方法,要使得依次处于1,2,3,4象限的直线的量化值越来愈大,反映出位置关系就行。

//2016华为机试题目:最大的凸多边形

#include<iostream>
#include<sstream>
#include<string>
#include<vector>
#include<cmath>
using namespace std;
struct Point
{
    double x;
    double y;
    //bool flag;
};
double quant_loc(Point p1,Point p2)
{
     double dx=p2.x-p1.x;
     double dy=p2.y-p1.y;
     double l=sqrt(dx*dx+dy*dy);
     double quant;
     if(l!=0)
     {
         if(dx>=0&&dy>=0)
             quant=dx/l;
         else if(dx>=0&&dy<0)
             quant=-dy/l+1;
         else if(dx<0&&dy<0)
             quant=-dx/l+2;
         else if(dx<0&&dy>=0)
             quant=dy/l+3;
     }
     else
         quant=-100;//表示同一个点
     return quant;
}
int find_next(int curr, double &last_quant,vector<Point> vec_p)//寻找该点的下一个连接点
{
    double curr_quant=5;
    int N=vec_p.size();
    int next;
    double quanti;
    vector<int> vec_quant(N,-1);
    for(int i=0;i<N;i++)
    {
        quanti=quant_loc(vec_p[curr],vec_p[i]);
        if(quanti>last_quant&&quanti<curr_quant)
        {
            curr_quant=quanti;
            next=i;
        }
        else if(quanti==last_quant)//方向系数相等时
        {
            curr_quant=quanti;
            next=i;
        }
        
    }
    last_quant=curr_quant;
    return next;


}
void main()
{
    Point p1;
    Point p2;
    double val;
    string Str;
    //cin>>p1.x>>p1.y>>p2.x>>p2.y;
    //val=quant_loc(p1,p2);
    //cout<<val<<endl;
    while(getline(cin,Str))
    {
        stringstream ss;
        ss.clear();
        ss.str("");
        ss<<Str;
        int N;
        ss>>N;//第一个数,点数
        ss>>Str;//输出剩余字符
        vector<Point> vec_p(N);
        double fistpx=100000000;//
        double fistpy=100000000;//
        int loc_first=0;
        for(int i=0;i<N;i++)//取出所有的数据点并找到第一个点
        {
            ss.clear();
            Str.erase(Str.begin());
            ss<<Str;
            ss>>vec_p[i].x;//取x
            ss>>Str;
            double tempx=vec_p[i].x;


            ss.clear();
            Str.erase(Str.begin());
            ss<<Str;
            ss>>vec_p[i].y;//取y
            ss>>Str;
            double tempy=vec_p[i].y;
            
            if(tempx<fistpx)
            {
                fistpx=tempx;//用于比较
                fistpy=tempy;
                loc_first=i;//记录第一个点
            }

            else if(tempx==fistpx&&tempy<fistpy)
            {
                fistpx=tempx;
                fistpy=tempy;
                loc_first=i;
            }
        }
        //for(int i=0;i<N;i++)
        //cout<<vec_p[i].x<<" "<<vec_p[i].y<<' '<<loc_first<<endl;
        int curr=loc_first;
        vector<int> linep;
        double last_quant=-1;
        linep.push_back(curr);
        int next=find_next(curr, last_quant,vec_p);//寻找该点的下一个连接点
        curr=next;
        linep.push_back(curr);
        while((vec_p[next].x!=vec_p[loc_first].x)||(vec_p[next].y!=vec_p[loc_first].y))
        {
            next=find_next(curr, last_quant, vec_p);
            curr=next;
            linep.push_back(curr);
        }
    for(int i=0;i<linep.size();i++)
    {
        cout<<vec_p[linep[i]].x<<','<<vec_p[linep[i]].y<<';';
    }
    cout<<endl;

    }
}
//还存在的问题:得到的结果在边上可能有点。

 

posted @ 2016-07-16 14:26  HomeWave  阅读(2257)  评论(0编辑  收藏  举报