程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 1178 Bumpy Objects問題(雖然是presentation error,沒辦法了)

1178 Bumpy Objects問題(雖然是presentation error,沒辦法了)

編輯:C++入門知識

其實求解思路倒也不復雜,就是先找到所有頂點的凸包(convex hull),然後找到這些凸包點中每條相鄰點連成的直線,同時找到直線在多邊形中的端點,如Object1中1,2,5,6這條直線,端點就是1,6。如果重心和這兩個點的連線和直線都是銳角的話,那麼這條直線就是穩定的,就可以找到題目要求的所謂最小點了。我的代碼自己測試是沒問題的,但怎麼都Presentation Error,無語。找凸包用的是Graham's Scan方法。


[cpp]
#include <iostream>  
#include <stack>  
#include <vector>  
#include <math.h>  
#include <iomanip>  
using namespace std; 
 
typedef struct point 

    double x; 
    double y; 
    int index;//記錄點的index  
}point; 
int cal_max(int index, vector<int>* myv, vector<point>* vertices, point mass); 
int find_stable(stack<int>* mys, vector<point>* vertices, point mass); 
void find_first(vector<point>* vertices); 
void sort(vector<point>* vertices); 
bool is_left(int index, stack<int>* mys, vector<point>* vertices); 
void find_convex_hull(vector<point>* vertices, stack<int>* mys); 
 
int main() 

    char name[20]; 
    vector<point> vertices; 
    stack<int> mys; 
    point mass; 
 
    while(cin>>name) 
    { 
        vertices.clear(); 
        while(mys.size() > 0) 
            mys.pop(); 
        if(strcmp(name,"#") == 0) 
        { 
            return 0; 
        } 
        cin>>mass.x>>mass.y; 
 
        point tmp;int index = 0; 
        while(cin>>tmp.x>>tmp.y) 
        { 
            if(tmp.x == 0 && tmp.y == 0) 
            { 
                break; 
            } 
            tmp.index = ++index; 
            vertices.push_back(tmp); 
        } 
        find_convex_hull(&vertices, &mys);//尋找凸包  
        int min = find_stable(&mys,&vertices,mass); 
        cout<<setw(20)<<setiosflags(ios::left)<<name<<setw(1)<<min<<endl; 
        //cout << name << ' ' << min << endl;  
    } 

//尋找凸包的Graham's Scan法  
//vertices:點集, mys:凸包的stack  
void find_convex_hull(vector<point>* vertices, stack<int>* mys) 

    find_first(vertices);//找到y坐標最小的點,放在第一位  
        sort(vertices);//根據和y0角度坐標排序  
        mys->push(0);mys->push(1);mys->push(2); 
        for(int i = 3; i < vertices->size(); i++) 
        { 
            int pos = mys->top(); 
            while(!is_left(i,mys,vertices)) 
            { 
                mys->pop(); 
            } 
            mys->push(i); 
        } 

//計算myv中index和index+1組成的直線的最大baseline  
//myv:凸包中的點集; vertices:點集; mass:重心坐標  
//返回最大的baseline  
int cal_max(int index, vector<int>* myv, vector<point>* vertices, point mass) 

    int start = index, end = index+1; 
    if(end == myv->size()) 
        end = 0; 
    start = myv->at(start);end = myv->at(end); 
    point left, right; 
    int max_index = 0, min_x = 65535, max_x = -65535; 
    for(int i = 0; i < myv->size(); i++) 
    { 
        int ano = myv->at(i); 
        double rate1 = (vertices->at(end).y - vertices->at(start).y)/(vertices->at(end).x - vertices->at(start).x); 
        double rate2 = (vertices->at(ano).y - vertices->at(start).y)/(vertices->at(ano).x - vertices->at(start).x); 
        if(vertices->at(ano).x == vertices->at(start).x) 
            rate2 = (vertices->at(ano).y - vertices->at(end).y)/(vertices->at(ano).x - vertices->at(end).x); 
        if(vertices->at(ano).x == vertices->at(start).x && vertices->at(end).x == vertices->at(start).x) 
            rate2 = rate1 = 1; 
        if(rate1 == rate2) 
        { 
            if(vertices->at(ano).index > max_index) 
                max_index = vertices->at(ano).index; 
            if(vertices->at(ano).x > max_x) 
            { 
                max_x = vertices->at(ano).x; 
                right = vertices->at(ano); 
            } 
            if(vertices->at(ano).x < min_x) 
            { 
                min_x = vertices->at(ano).x; 
                left = vertices->at(ano); 
            } 
        } 
    } 
    //判斷重心是否在范圍內  
    point vec1, vec2; 
    vec1.x = mass.x - left.x; vec1.y = mass.y - left.y; 
    vec2.x = right.x - left.x; vec2.y = right.y - left.y; 
    if((vec1.x*vec2.x + vec1.y*vec2.y) < 0) 
        return -1; 
    vec1.x = mass.x - right.x; vec1.y = mass.y - right.y; 
    vec2.x = left.x - right.x; vec2.y = left.y - right.y; 
    if((vec1.x*vec2.x + vec1.y*vec2.y) < 0) 
        return -1; 
    return max_index; 

 
//找到穩定的最小baseline  
//mys:凸包中的點集;vertices:點集; mass:重心坐標  
//返回最小的baseline  
int find_stable(stack<int>* mys, vector<point>* vertices, point mass) 

    vector<int> myv; 
    while(mys->size() > 0) 
    { 
        myv.push_back(mys->top()); 
        mys->pop(); 
    } 
    int min_index = 65535; 
    for(int i = 0; i < myv.size(); i++) 
    { 
        //確定直線公式  
         
        int this_min = cal_max(i,&myv,vertices,mass); 
        if(this_min >=0 && this_min < min_index) 
        { 
            min_index = this_min; 
        } 
    } 
    if(min_index == 65536) 
        return 0; 
    return min_index; 

 
//判斷向量方向是否向左  
//index:將要判斷的點的位置; mys:凸包中的點集; vertices:點集  
//true: 滿足要求; false:不滿足,朝右  
bool is_left(int index, stack<int>* mys, vector<point>* vertices) 

    int first = mys->top();mys->pop(); 
    int second = mys->top();mys->push(first); 
 
    point vec1,vec2; 
    point vec0;vec0.x = 0; 
    vec1.y = vertices->at(first).y - vertices->at(second).y; 
    vec1.x = vertices->at(first).x - vertices->at(second).x; 
    vec2.y = vertices->at(index).y; 
    vec2.x = vertices->at(index).x; 
    vec0.y = vertices->at(first).y - vertices->at(first).x*vec1.y/vec1.x; 
 
    if(vec1.x > 0) 
    { 
        if(vec2.y >= vec2.x*vec1.y/vec1.x + vec0.y) 
            return true; 
    } 
    else if(vec1.x < 0) 
    { 
        if(vec2.y <= vec2.x*vec1.y/vec1.x + vec0.y) 
            return true; 
    } 
    else 
    { 
        if(vec1.y * (vec2.x - vertices->at(first).x) <= 0) 
            return true; 
    } 
    return false; 

 
//找到最小y坐標的點,放在0位置  
//vertices:點集  
void find_first(vector<point>* vertices) 

    for(int i = 0; i < vertices->size(); i++) 
    { 
        if(vertices->at(i).y < vertices->at(0).y) 
            swap(vertices->at(i), vertices->at(0)); 
    } 

//根據和0位置點的級角排序除第一個以外的所有點(偷懶用的插入排序...)  
//vertices:點集  
void sort(vector<point>* vertices) 

    for(int i = 1; i < vertices->size(); i++) 
    { 
        for(int j = i; j > 1; j--) 
        { 
            //使用向量余弦定理做,明天  
            point vec0,vec1,vec2; 
            vec0.x = 1;vec0.y = 0; 
            vec1.y = vertices->at(j).y - vertices->at(0).y; 
            vec1.x = vertices->at(j).x - vertices->at(0).x; 
            vec2.y = vertices->at(j-1).y - vertices->at(0).y; 
            vec2.x = vertices->at(j-1).x - vertices->at(0).x; 
            double cos1 = (vec1.x*vec0.x + vec1.y*vec0.y) / sqrt((vec1.x*vec1.x + vec1.y*vec1.y)*(vec0.x*vec0.x + vec0.y*vec0.y)); 
            double cos2 = (vec2.x*vec0.x + vec2.y*vec0.y) / sqrt((vec2.x*vec2.x + vec2.y*vec2.y)*(vec0.x*vec0.x + vec0.y*vec0.y)); 
            if(cos1 > cos2) 
            { 
                swap(vertices->at(j),vertices->at(j-1)); 
            } 
            /*double rate1 = (vertices->at(j).y - vertices->at(0).y)/(vertices->at(j).x - vertices->at(0).x);
            double rate2 = (vertices->at(j-1).y - vertices->at(0).y)/(vertices->at(j-1).x - vertices->at(0).x);
            if(vertices->at(j).x - vertices->at(0).x == 0)
                rate1 = 65535;
            if(vertices->at(j-1).x - vertices->at(0).x == 0)
                rate2 = 65535;
            if(rate1*rate2 > 0 && rate1 < rate2)
            {
                swap(vertices->at(j),vertices->at(j-1));
            }
            else if(rate1*rate2 < 0 && rate1 < 0)
            {
                swap(vertices->at(j),vertices->at(j-1));
            }
            else if(rate1*rate2 == 0 && (vertices->at(j).x > vertices->at(0).x || vertices->at(j-1).x < vertices->at(0).x))
            {
                swap(vertices->at(j),vertices->at(j-1));
            }*/ 
        } 
    } 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved