在一个二维的花园中,有一些用 (x, y) 坐标表示的树。由于安装费用十分昂贵,你的任务是先用最短的绳子围起所有的树。只有当所有的树都被绳子包围时,花园才能围好栅栏。你需要找到正好位于栅栏边界上的树的坐标。
思路:标准的凸包问题,这里使用了Andrew 算法
代码:
class Solution
{
public:
struct node
{
int x,y;
} a[1000005],b[1000005],ansV[1000005];
static bool cmp(node a, node b)
{
if(a.y == b.y)
return a.x < b.x;
return a.y < b.y;
}
int Cross(node a,node b,node c)
{
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
int Tbag(int n)
{
sort(a,a+n,cmp);
int m=0,i;
for(i=0; i<n; i++)
{
while(m > 1 && Cross(b[m-2],b[m-1],a[i]) < 0) m--;
b[m++]=a[i];
}
int k=m;
for(i=n-2; i>=0; i--)
{
while(m > k && Cross(b[m-2],b[m-1],a[i]) < 0) m--;
b[m++]=a[i];
}
if(n >1)
m--;
return m;
}
vector<vector<int>> outerTrees(vector<vector<int>>& points)
{
int t = points.size();
int xx, yy;
for(int i = 0; i < t; i++)
{
a[i].x = points.at(i).at(0);
a[i].y = points.at(i).at(1);
}
xx=a[0].x;
yy=a[0].y;
for(int i = 0; i < t; i++)
{
a[i].x -= xx;
a[i].y -= yy;
}
int top = Tbag(t);
int k = 0;
vector<vector<int>> ans;
for(int i = 0; i<top; i++)
{
ansV[k++] = b[i];
}
for(int i = t-2; i>0; i--)
{
if(Cross(a[0],a[i],a[t-1]) == 0)
{
ansV[k++] = a[i];
}
else break;
}
sort(ansV,ansV+k,cmp);
for(int i = 0; i<k ; i++)
{
if(i&&ansV[i].x==ansV[i-1].x&&ansV[i].y==ansV[i-1].y) continue;
vector<int>tmp;
tmp.push_back(ansV[i].x+xx);
tmp.push_back(ansV[i].y+yy);
ans.push_back(tmp);
}
return ans;
}
};