编程语言
首页 > 编程语言> > 2022春季 哈工大 硕士算法设计与分析 实验一分治算法

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

 

标签:const,temp,nums,second,算法,哈工大,2022,pair,first
来源: https://www.cnblogs.com/WTSRUVF/p/16350512.html