题目链接:https://vjudge.net/problem/Gym-101635K
解题思路:
寻找最小覆盖矩形使得能把蛋糕上面所有的点都覆盖,求出他的宽度,高度不限.
那么首先求出n个点组成的凸包.枚举凸包上的所有边,再找凸包上的一个离这条边最远的点,经过此点做边的平行线。
那么此两条平行线无限延长肯定能覆盖所有的点,宽度就是两平行直线的距离.
取每条边都这么做然后最后取答案最小的那一条边.
那么怎么找到边对应的那个点呢?
1.我们按凸包逆时针点枚举,对应边的那个最远点,一定是个"凸值",即逆时针枚举距离值会先增后减,(特殊情况是一开始枚举第一个点就是极值),求凸值就可以用三分来求,因为特殊情况有可能不是凸函数,所以区间至少保留4个以上,3个时退出.
2.叉积法同样是按逆时针枚举凸包上的点,假设现在考虑边(i,i+1),做向量(i+1)->i,从(i+1)->(i+2),(i+2)->(i+3)。。。直到两个叉积>=0
也就是(i+1)->i*j->(j+1)>=0 , 那么j点就是最远的,可以用叉积面积方式理解(底是边(i,i+1),高就是点到直线距离),也可以很容易理解用j这个点做边的平行线,所有点一定都会被夹在中间.
三分法:
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int mx = 2e5 + 10;
int n,top,_x,_y,q[mx*2],m;
double len;
struct node
{
ll x,y;
}s[mx],tubeg[mx],w;
ll judge(node p1,node p2,node p0)//面积公式判断正负值
{
ll ans = (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
return ans;
}
bool cmp(node a,node b)
{
ll c = judge(w,b,a);//极角排序,同角度按距离从小到大排
if(!c) return pow(a.x-w.x,2)+pow(a.y-w.y,2) < pow(b.x-w.x,2)+pow(b.y-w.y,2);
return c < 0;
}
void Graham()
{
for(int i=0;i1&&judge(tubeg[top-2],s[i],tubeg[top-1])>=0) top--;//在矢量左侧的点都去掉
tubeg[top++] = s[i];
}
}
double dist(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double across(node c,node a,node b)
{
return fabs((c.y-a.y)*(b.x-a.x) - (c.x-a.x)*(b.y-a.y));
}
double Get(int x,node a,node b)
{
node c = tubeg[x];
return across(c,a,b) / len;
}
double sanfen(int l,int r,node a,node b)
{
while(l>1;
int mmid = mid+1;
if(Get(q[mid],a,b)>Get(q[mmid],a,b))
r = mmid;
else l = mid;
}
return max(Get(q[l],a,b),max(Get(q[r],a,b),Get(q[r-1],a,b)));
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int a,b,p = 0;
for(int i=0;i
叉积法:
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int mx = 2e5 + 10;
int n,top,_x,_y,m;
double len;
struct node
{
ll x,y;
}s[mx],tubeg[mx],w;
ll judge(node p1,node p2,node p0)//面积公式判断正负值
{
ll ans = (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);
return ans;
}
ll judge2(node a,node b)
{
return a.x*b.y - b.x*a.y;
}
bool cmp(node a,node b)
{
ll c = judge(w,b,a);//极角排序,同角度按距离从小到大排
if(!c) return pow(a.x-w.x,2)+pow(a.y-w.y,2) < pow(b.x-w.x,2)+pow(b.y-w.y,2);
return c < 0;
}
void Graham()
{
for(int i=0;i1&&judge(tubeg[top-2],s[i],tubeg[top-1])>=0) top--;//在矢量左侧的点都去掉
tubeg[top++] = s[i];
}
}
double dist(node a,node b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double Get(int x,node a,node b)
{
node c = tubeg[x];
return fabs( judge(b,c,a) / len );
}
node cut(node a,node b)
{
return node{a.x-b.x,a.y-b.y};
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int a,b,p = 0;
for(int i=0;i