• 2022春季 哈工大 硕士算法设计与分析 实验一分治算法


    枚举凸包:

    算法思想:
    每四个点判断是否有其中一个点在另外三个点的包围内,
    如果是,
    则标记为内点,重复选取,直至没有内点
    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <vector>
    #include <utility>
    #include <ctime>
    using namespace std;
    int n;
    vector<int> temp;
    bool vis[1010];
    // 求平行四边形面积,因为求三角形会有精度损失
    double area(const pair<double, double>& a, const pair<double, double>& b,
               const pair<double, double>& c)
    {
        double ret = fabs((b.first - a.first) * (c.second - a.second) - (c.first - a.first)* (b.second - a.second));
        return ret;
    }
    //如果d在三角形abc内部,则Sabc = Sabd + Sacd + Sbcd
    void check(const pair<double, double>& a, const pair<double, double>& b,
               const pair<double, double>& c, const pair<double, double>& d,
               const int& id)
    {
        double A = area(a, b, c), B = area(a, b, d), C = area(a, c, d), D = area(b, c, d);
        if(A == B + C + D && B != 0 && C != 0 && D != 0)
            vis[id] = 1;
    }
    
    // 对每四个点都进行判断,标记内部点
    void Convex(vector<pair<double, double> >& nums, int k)
    {
        if(temp.size() == 4)
        {
    
            check(nums[temp[0]], nums[temp[1]], nums[temp[2]], nums[temp[3]], temp[3]);
            check(nums[temp[0]], nums[temp[1]], nums[temp[3]], nums[temp[2]], temp[2]);
            check(nums[temp[0]], nums[temp[2]], nums[temp[3]], nums[temp[1]], temp[1]);
            check(nums[temp[1]], nums[temp[2]], nums[temp[3]], nums[temp[0]], temp[0]);
            return;
        }
        for(int i = k + 1; i < nums.size(); i++)
        {
            temp.push_back(i);
            Convex(nums, i);
            temp.pop_back();
        }
    }
    
    
    
    int main()
    {
        int isborder[101][101];
        memset(isborder, 0, sizeof(isborder));
        vector<pair<double, double> > nums; //存储点
        memset(vis, 0, sizeof(vis));
        cin >> n;
        if(n < 3)
        {
            cout << "Points not enough" << endl;
            return 0;
        }
        for(int i = 0; i < n; i++)
        {
            double x, y;
            cin >> x >> y;
            isborder[(int)x][(int)y] = -1;
    
            nums.push_back(pair<double, double> (x, y));
        }
        clock_t startTime, endTime;
        startTime = clock();
    
        Convex(nums, -1);
        endTime = clock();
    
        cout << "result: " << endl;
        for(int i = 0; i < n; i++)
        {
            if(vis[i] == 0)
            {
                cout << nums[i].first << " " << nums[i].second << endl;
                isborder[(int)nums[i].first][(int)nums[i].second] = 1;
    
            }
        }
            for(int i = 0; i <= 100; i++)
        {
            for(int j = 0; j <= 100; j++)
            {
                if(isborder[i][j] == -1)
                    cout << "6";
                else if(isborder[i][j] == 0)
                    cout << "*";
                else
                    cout << "7";
            }
            cout << endl;
    
        }
        cout << "The run time is: " <<(double)(endTime - startTime) << "ms" << endl;
    
        return 0;
    }
    View Code

    graham凸包:

    算法思想:
    1、求y值最小的点p
    2、以p为原点,将其他点按极角大小逆时针排序
    3、将前三个点放入vector,遍历剩余点,如果vector[size - 2] vector[size - 1] points[i]不是逆时针方向,
    则pop_back()
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <utility>
    #include <ctime>
    using namespace std;
    int n;
    
    bool cmp1(const pair<double, double>& a, const pair<double, double>& b)
    {
        return a.second < b.second;
    }
    //bool cmp2(const pair<double, double>& a, const pair<double, double>& b)
    //{
    //    double cita1 = atan(a.second / a.first);
    //    cita1 = cita1 < 0 ? cita1 + 3.14 : cita1;
    //    double cita2 = atan(b.second / b.first);
    //    cita2 = cita2 < 0 ? cita2 + 3.14 : cita2;
    //    if(cita1 == cita2)
    //        return a.first < b.first;
    //    else if(cita1 < cita2)
    //        return 1;
    //    else return 0;
    //}
    
    int cross(const pair<double, double> &a, const pair<double, double> &b, const pair<double, double> &c)
    {
        return (b.first - a.first) * (c.second - a.second) - (c.first - a.first) * (b.second - a.second);
    }
    
    bool cmp2(const pair<double, double>& a, const pair<double, double>& b)
    {
        pair<double, double> c;
        c.first = 0;
        c.second = 0;
        if(cross(c, a, b)==0)
            return a.first < b.first;
        else
            return cross(c, a, b) > 0;
    
    }
    
    vector<pair<double, double> > Graham(vector<pair<double, double> > &nums)
    {
        // 求最小y的点point,用了个排序
        sort(nums.begin(), nums.end(), cmp1);
        double x = nums[0].first, y = nums[0].second;
        // 将所有的点移动到point为原点的坐标系下
        for(int i = 0; i < nums.size(); i++)
        {
            nums[i].first -= x;
            nums[i].second -= y;
        }
        // 按照极角排序
        sort(nums.begin() + 1, nums.end(), cmp2);
    
    
        vector<pair<double, double> > ret;
        ret.push_back(nums[0]);
        ret.push_back(nums[1]);
        ret.push_back(nums[2]);
        // 遍历剩余结点,如果当前结点不在上一个结点的逆时针方向,则移除上一个结点,直至符合
        for(int i = 3; i < nums.size(); i++)
        {
            while(ret.size() >= 2 && cross(ret[ret.size() - 2], ret[ret.size() - 1], nums[i]) <= 0)
                ret.pop_back();
            ret.push_back(nums[i]);
        }
        for(int i = 0; i < ret.size(); i++)
            ret[i].first += x, ret[i].second += y;
        return ret;
    }
    
    
    int main()
    {
        int isborder[101][101];
        memset(isborder, 0, sizeof(isborder));
        vector<pair<double, double> > nums;
        cin >> n;
        if(n < 3)
        {
            cout << "Points not enough" << endl;
            return 0;
        }
        for(int i = 0; i < n; i++)
        {
            double x, y;
            cin >> x >> y;
            isborder[(int)x][(int)y] = -1;
            nums.push_back(pair<double, double> (x, y));
        }
    
        clock_t startTime, endTime;
        startTime = clock();
    
        vector<pair<double, double> > ret = Graham(nums);
        endTime = clock();
        cout << "result: " << endl;
        for(int i = 0; i < ret.size(); i++)
        {
    
            cout << ret[i].first << " " << ret[i].second << endl;
            isborder[(int)ret[i].first][(int)ret[i].second] = 1;
    
        }
        for(int i = 0; i <= 100; i++)
        {
            for(int j = 0; j <= 100; j++)
            {
                if(isborder[i][j] == -1)
                    cout << "6";
                else if(isborder[i][j] == 0)
                    cout << "*";
                else
                    cout << "7";
            }
            cout << endl;
    
        }
        cout << "The run time is: " <<(double)(endTime - startTime) << "ms" << endl;
    
    
    
        return 0;
    }
    View Code

    分治凸包:

    算法思想:
    1、求各点坐标x值的中点m
    2、以x = m为分界线将点集合分为Ql和Qr两个子集和
    3、递归在Ql和Qr中求凸包
    4、将两个凸包按规则合并到一起
    5、凸包算法使用graham算法
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <utility>
    #include <ctime>
    using namespace std;
    int n;
    
    bool cmp1(const pair<double, double>& a, const pair<double, double>& b)
    {
        return a.second < b.second;
    }
    //bool cmp2(const pair<double, double>& a, const pair<double, double>& b)
    //{
    //    double cita1 = atan(a.second / a.first);
    //    cita1 = cita1 < 0 ? cita1 + 3.14 : cita1;
    //    double cita2 = atan(b.second / b.first);
    //    cita2 = cita2 < 0 ? cita2 + 3.14 : cita2;
    //    if(cita1 == cita2)
    //        return a.first < b.first;
    //    else if(cita1 < cita2)
    //        return 1;
    //    else return 0;
    //}
    bool cmp3(const pair<double, double>& a, const pair<double, double>& b)
    {
        return a.first < b.first;
    }
    
    int cross(const pair<double, double> &a, const pair<double, double> &b, const pair<double, double> &c)
    {
        return (b.first - a.first) * (c.second - a.second) - (c.first - a.first) * (b.second - a.second);
    }
    
    bool cmp2(const pair<double, double>& a, const pair<double, double>& b)
    {
        pair<double, double> c;
        c.first = 0;
        c.second = 0;
        if(cross(c, a, b)==0)
            return a.first < b.first;
        else
            return cross(c, a, b) > 0;
    
    }
    
    vector<pair<double, double> > Graham(vector<pair<double, double> > &nums, int l, int r)
    {
        vector<pair<double, double> > ret;
        // 边界条件
        if(l > r)
            return ret;
    
        if(r - l + 1 <= 3)
        {
            for(int i = l; i <= r; i++)
                ret.push_back(nums[i]);
            return ret;
        }
    
        // 划分、递归
        int m = (l + r) / 2;
        vector<pair<double, double> > ret1 = Graham(nums, l, m);
        vector<pair<double, double> > ret2 = Graham(nums, m + 1, r);
        vector<pair<double, double> > temp;
        for(int i = 0; i < ret1.size(); i++)
            temp.push_back(ret1[i]);
        for(int i = 0; i < ret2.size(); i++)
            temp.push_back(ret2[i]);
    
        // 求最小y的点point,用了个排序
        sort(temp.begin(), temp.end(), cmp1);
        double x = temp[0].first, y = temp[0].second;
        // 将所有的点移动到point为原点的坐标系下
        for(int i = 0; i < temp.size(); i++)
        {
            temp[i].first -= x;
            temp[i].second -= y;
        }
        // 按极角排序
        sort(temp.begin() + 1, temp.end(), cmp2);
    
    
        ret.push_back(temp[0]);
        ret.push_back(temp[1]);
        ret.push_back(temp[2]);
        // 遍历剩余结点,如果当前结点不在上一个结点的逆时针方向,则移除上一个结点,直至符合
        for(int i = 3; i < temp.size(); i++)
        {
            while(ret.size() >= 2 && cross(ret[ret.size() - 2], ret[ret.size() - 1], temp[i]) <= 0)
                ret.pop_back();
            ret.push_back(temp[i]);
        }
        for(int i = 0; i < ret.size(); i++)
            ret[i].first += x, ret[i].second += y;
        return ret;
    }
    
    
    int main()
    {
        int isborder[101][101];
        memset(isborder, 0, sizeof(isborder));
        vector<pair<double, double> > nums;
        cin >> n;
        if(n < 3)
        {
            cout << "Points not enough" << endl;
            return 0;
        }
    
        for(int i = 0; i < n; i++)
        {
            double x, y;
            cin >> x >> y;
            isborder[(int)x][(int)y] = -1;
            nums.push_back(pair<double, double> (x, y));
        }
        clock_t startTime, endTime;
        startTime = clock();
        // 先将所有的点按x排序,这样简便划分
        sort(nums.begin(), nums.end(), cmp3);
    
        vector<pair<double, double> > ret = Graham(nums, 0, nums.size() - 1);
        endTime = clock();
    
        cout << "result: " << endl;
        for(int i = 0; i < ret.size(); i++)
        {
    
            cout << ret[i].first << " " << ret[i].second << endl;
            isborder[(int)ret[i].first][(int)ret[i].second] = 1;
        }
        for(int i = 0; i <= 100; i++)
        {
            for(int j = 0; j <= 100; j++)
            {
                if(isborder[i][j] == -1)
                    cout << "6";
                else if(isborder[i][j] == 0)
                    cout << "*";
                else
                    cout << "7";
            }
            cout << endl;
    
        }
    
    
    
    
        cout << "The run time is: " <<(double)(endTime - startTime) << "ms" << endl;
    
    
        return 0;
    }
    View Code
  • 相关阅读:
    YTU 2481: 01字串
    smarty的自定义函数
    $_SERVER['SCRIPT_FLENAME']与__FILE__
    pdo中query()与prepare().execute()
    pdo中bindParam()与bindValue的区别
    pdo简介--错误与错误处理
    pdo的三个预定义类,PDO PDOStatement PDOException
    根目录 上级目录 当前目录
    反射机制(转)
    log4j 日志配置
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/16350512.html
Copyright © 2020-2023  润新知