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