阿里笔试——城堡问题 标签: C++算法编程阿里城堡 2017-07-09 16:09 62人阅读 评论(0)
题目:
将军大胜归来,夺取许多城堡(xi,yi)。国王许可,你站在任意的城堡上,选择任意视角,看得见的城堡都是你的,包括你站的城堡,但头不能动。而且你不能站在城堡构成的凸焦点上。将军的视角刚好小于180度(无限接近180度),可以看得无限远。请计算出将军最多能得多少城堡。如果所有的城堡都在凸焦点上,那么将军一个城堡也得不到。
输入:
第一行,整数m,表示接下来有m行。接下来的m行,每行都有2个数,表示一个城堡的坐标。
输出:
最多获得的城堡个数。
输入范例:
0 0
0 2
1 0
1 2
0.2 1.8
输出范例:
4
解析:
假设将军站在某个城堡A上,然后朝一个方向看,为了最可能多的包含多的城堡,假设其视线的一个边缘恰好经过某个(或者某些在一条线上的)城堡B,然后分别计算该直线两侧的点的个数n1和 n2,还得计算射线AB上的城堡个数 n0(至少为2,因为A和B在其上)。如果A是凸焦点则为0,否则为n0 + max(n1,n2)。然后将军遍历所有站立的城堡,返回最大的。
代码:
#include <iostream> #include <vector> #include <numeric> #include <limits> using namespace std; // 请完成下面这个函数,实现题目要求的功能 //当然,你也可以不按照这个模板来作答,完全按照自己的想法来 ^-^ struct Point { // 定义点类型 double x, y; Point(double x1 = 0, double y1 = 0) :x(x1), y(y1) {} }; Point castleHelp(Point p1, Point p2, Point p3) { // 输入3点,输出位置和夹角 Point ret; p2.x -= p1.x; p2.y -= p1.y; p3.x -= p1.x; p3.y -= p1.y; ret.x = p2.x * p3.y - p3.x * p2.y; ret.y = acos((p2.x * p3.x + p2.y * p3.y) / sqrt((p2.x * p2.x + p2.y * p2.y) * (p3.x * p3.x + p3.y * p3.y))); return ret; } int castle(vector<Point> points) { int ret(0), vl(points.size()); if (vl < 4) return 0; for (int k1(0); k1 < vl; ++k1) for (int k2(0); k2 < vl; ++k2) { if (k1 == k2) continue; int n1(0), n2(0), n0(2); double theta1(0), theta2(0); for (int k3(0); k3 < vl; ++k3) { if (k3 == k2 || k3 == k1) continue; auto p(castleHelp(points[k1], points[k2], points[k3])); if (p.y < 1e-9) ++n0; // 在射线AB上 else { if (p.x > 0) ++n1, theta1 = theta1 < p.y ? p.y : theta1; // 在直线一侧 else if(0 < p.x) ++n2, theta2 = theta2 < p.y ? p.y : theta2; // 在直线另一侧 } } if (acos(-1) < theta1 + theta2) { // 判断是否则为凸焦点 n1 = n1 < n2 ? n2 + n0 : n1 + n0; ret = ret < n1 ? n1 : ret; } } return ret; } int main() { int points_size(0); cout << "请输入点的个数:"; cin >> points_size; cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); vector<Point> points; Point points_item; cout << "请依次输入点的坐标: x y" << endl; for (int points_i(0); points_i < points_size; ++points_i) { cin >> points_item.x >> points_item.y; cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); points.push_back(points_item); } cout << castle(points) << endl; return 0; }
lmjy