热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Bzoj1185最小矩阵覆盖[旋转卡壳+凸包+处理[0]情况]

题目链接题目大意:就是给你若干个点用一个最小的矩形把这些点覆盖掉就是给你若干个点用一个最小的矩形把这些点覆盖掉就是给你若干个点用一个最小的矩形把这些点覆盖掉解题思路&

题目链接



题目大意:
就是给你若干个点用一个最小的矩形把这些点覆盖掉就是给你若干个点用一个最小的矩形把这些点覆盖掉



解题思路:
1.首先很明显我们可以对这些点求一个凸包,那么答案的矩形的一定是卡在凸包外面的1.首先很明显我们可以对这些点求一个凸包,那么答案的矩形的一定是卡在凸包外面的1.,
2.我们手动模一下就是逐渐增加凸包上面的点数,去看一下最小的矩形覆盖情况,就是矩形的一条边有两个点在上面就是和凸多边形一条边重合,其他三条边就卡在其他三个点上面。2.我们手动模一下就是逐渐增加凸包上面的点数,去看一下最小的矩形覆盖情况,就是矩形的一条边有两个点在上面就是和凸多边形一条边重合,其他三条边就卡在其他三个点上面。2.,,,
3.那么我们就可以O(n)枚举一下矩形卡着哪条边,我们通过用发现up点和bottem围成的三角形是一个单峰函数。left和right点的在bottom处的投影也是一个凹函数3.那么我们就可以O(n)枚举一下矩形卡着哪条边,我们通过用发现up点和bottem围成的三角形是一个单峰函数。left和right点的在bottom处的投影也是一个凹函数3.O(n),upbottemleftrightbottom



在这里插入图片描述



#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mid ((l + r) >> 1)
#define Lson rt <<1, l , mid
#define Rson rt <<1|1, mid &#43; 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define _for(i,a,b) for( int i &#61; (a); i <(b); &#43;&#43;i)
#define _rep(i,a,b) for( int i &#61; (a); i <&#61; (b); &#43;&#43;i)
#define for_(i,a,b) for( int i &#61; (a); i >&#61; (b); -- i)
#define rep_(i,a,b) for( int i &#61; (a); i > (b); -- i)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define hash Hash
#define next Next
#define f first
#define s second
using namespace std;
const int maxn &#61; 1e5 &#43; 10;
const double eps &#61; 1e-10;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
struct Point//点或向量
{double x, y;Point() {}Point(double x, double y) :x(x), y(y) {}
};
typedef Point Vector;
double minsqr &#61; 1e12;
int n;
Point ploy[maxn], sta[maxn], ans[10];
int dcmp(double x)//精度三态函数(>0,<0,&#61;0)
{if (fabs(x) < eps)return 0;else if (x > 0)return 1;return -1;
}
double Dot(Vector a, Vector b)//内积
{return a.x*b.x &#43; a.y*b.y;
}
Vector operator &#43; (Vector a, Vector b)//向量加法
{return Vector(a.x &#43; b.x, a.y &#43; b.y);
}
Vector operator - (Vector a, Vector b)//向量减法
{return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p)//向量数乘
{return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p)//向量数除
{return Vector(a.x / p, a.y / p);
}
double Distance(Point a, Point b)//两点间距离
{return sqrt((a.x - b.x)*(a.x - b.x) &#43; (a.y - b.y)*(a.y - b.y));
}
bool operator &#61;&#61; (const Point &a, const Point &b)//向量相等
{return dcmp(a.x - b.x) &#61;&#61; 0 && dcmp(a.y - b.y) &#61;&#61; 0;
}bool operator<(Point a,Point b)
{if(!dcmp(a.y-b.y)) return a.x<b.x;return a.y<b.y;
}double Cross(Vector a, Vector b)//外积
{return a.x*b.y - a.y*b.x;
}double DistanceToLine(Point A, Point M, Point N)//点A到直线MN的距离,Error:MN&#61;0
{return fabs(Cross(A - M, A - N) / Distance(M, N));
}double relation(Point A, Point B, Point C)
{return Dot(B - A, C - A) / Distance(A,B) / Distance(A,B);
}
//求C在AB所在直线的垂足P坐标
Point pedal(Point A, Point B, Point C)
{double r &#61; relation(A,B,C);Point res;res.x &#61; A.x &#43; r * (B.x - A.x);res.y &#61; A.y &#43; r * (B.y - A.y);return res;
}bool cmp(Point a,Point b)
{if(!dcmp(a.x-b.x)) return a.y<b.y;return a.x<b.x;
}
int top &#61; 0;
void Graham() {sort(ploy,ploy&#43;n,cmp);for(int i &#61; 0; i < n; &#43;&#43; i) {while(top >&#61; 2 && dcmp(Cross(sta[top]-sta[top-1],ploy[i]-sta[top-1])) <&#61; 0) top--;sta[&#43;&#43;top] &#61; ploy[i];}int tmp &#61; top;for(int i &#61; n - 2; i >&#61; 0; -- i) {while(top >&#61; tmp &#43; 1 && dcmp(Cross(sta[top]-sta[top-1],ploy[i]-sta[top-1])) <&#61; 0) top--;sta[&#43;&#43; top] &#61; ploy[i];}top --;
}void qiake() {int left &#61; 1, right &#61; 1, up &#61; 1;for(int i &#61; 1; i <&#61; top; &#43;&#43; i) {while(dcmp(Cross(sta[i]-sta[up&#43;1],sta[i&#43;1]-sta[up&#43;1]) - Cross(sta[i]-sta[up],sta[i&#43;1]-sta[up])) >&#61; 0) up &#61; up % top &#43; 1;while(dcmp(Dot(sta[right&#43;1] - sta[i],sta[i&#43;1]-sta[i]) - Dot(sta[right]-sta[i],sta[i&#43;1]-sta[i])) >&#61; 0) right &#61; right % top &#43; 1;if(i &#61;&#61; 1) left &#61; right;while(dcmp(Dot(sta[i]-sta[i&#43;1],sta[left&#43;1]-sta[i&#43;1]) - Dot(sta[i]-sta[i&#43;1],sta[left]-sta[i&#43;1])) >&#61; 0) left &#61; left % top &#43; 1;double L &#61; DistanceToLine(sta[up],sta[i],sta[i&#43;1]);double Len &#61; Distance(sta[i],sta[i&#43;1]);//i 和 i &#43; 1 点之间的长度double botten &#61; Dot(sta[right]-sta[i],sta[i&#43;1]-sta[i]) / Len &#43; Dot(sta[i]-sta[i&#43;1],sta[left]-sta[i&#43;1]) / Len - Len;if(dcmp(minsqr - botten * L) > 0) {//逆时针存储矩形minsqr &#61; botten * L;ans[0] &#61; pedal(sta[i],sta[i&#43;1],sta[right]);ans[1] &#61; pedal(ans[0],sta[right],sta[up]);ans[2] &#61; pedal(ans[1],sta[up],sta[left]);ans[3] &#61; pedal(sta[i],sta[i&#43;1],sta[left]);}}
}int main()
{IOS;cin >> n;for(int i &#61; 0; i < n; &#43;&#43; i) {double x, y;cin >> x >> y;ploy[i] &#61; (Point){x,y};}Graham();qiake();cout << fixed << setprecision(5) << minsqr << endl;int tmp &#61; 0;for(int i &#61; 0; i <&#61; 3; i &#43;&#43;)if(ans[i]<ans[tmp]) tmp &#61; i;for(int i &#61; 0; i < 4; &#43;&#43; i)cout << fixed << setprecision(5) << ans[(i &#43; tmp) % 4].x &#43; eps/*防止-0的出现*/ << " " << ans[(i &#43; tmp) % 4].y &#43; eps << endl;
}



推荐阅读
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 本文探讨了如何在模运算下高效计算组合数C(n, m),并详细介绍了乘法逆元的应用。通过扩展欧几里得算法求解乘法逆元,从而实现除法取余的计算。 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • Java 中的 BigDecimal pow()方法,示例 ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
author-avatar
好kc好先生之家
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有