bzoj 1038 [ZJOI2008]瞭望塔(半平面交)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=1038
【题意】
找一个最低塔高使可以看到村庄的每一个角落。
【思路】
半平面交
能够看到一个线段的点都在该线段所在直线的上方,如果能看到所有的线段则该区域就是所有线段所在直线的半平面交。
最低塔高就是要求这个区域与村庄之间的最短距离。无论是交还是村庄都可以看作是分段的一次函数,所以最近距离一定在分段点处取得。分别枚举交和村庄的分段点即可。
需要注意的有:预先添加两个边界。求最近距离时先判断一下x的关系,否则谁知道交点飞到哪去T_T
【代码】
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; const int N = ;
const double bond = ;
const double eps = 1e-; struct Pt {
double x,y;
Pt (double x=,double y=):x(x),y(y){}
};
typedef Pt vec; vec operator + (Pt a,Pt b) { return vec(a.x+b.x,a.y+b.y); }
vec operator - (Pt a,Pt b) { return vec(a.x-b.x,a.y-b.y); }
vec operator * (Pt a,double p) { return vec(a.x*p,a.y*p); } double cross(Pt a,Pt b) { return a.x*b.y-a.y*b.x; } struct Line {
Pt p; vec v; double ang;
Line () {}
Line (Pt p,vec v) :p(p),v(v){ ang=atan2(v.y,v.x); }
bool operator < (const Line& rhs) const {
return ang<rhs.ang;
}
}; bool onleft(Line L,Pt p) { return cross(L.v,p-L.p)>; }
Pt LineInter(Line a,Line b)
{
vec u=a.p-b.p;
double t=cross(b.v,u)/cross(a.v,b.v);
return a.p+a.v*t;
}
vector<Pt> HPI(vector<Line> L)
{
int n=L.size();
sort(L.begin(),L.end());
int f,r;
vector<Pt> p(n) , ans;
vector<Line> q(n);
q[f=r=]=L[];
for(int i=;i<n;i++) {
while(f<r&&!onleft(L[i],p[r-])) r--;
while(f<r&&!onleft(L[i],p[f])) f++;
q[++r]=L[i];
if(fabs(cross(q[r].v,q[r-].v))<eps) {
r--;
if(onleft(q[r],L[i].p)) q[r]=L[i];
}
if(f<r) p[r-]=LineInter(q[r-],q[r]);
}
while(f<r&&!onleft(q[f],p[r-])) r--;
if(r-f<=) return ans;
p[r]=LineInter(q[r],q[f]);
for(int i=f;i<=r;i++) ans.push_back(p[i]);
return ans;
} vector<Line> L;
vector<Pt> p,np;
int n; int main()
{
scanf("%d",&n);
double x[N],y[N];
for(int i=;i<=n;i++) {
scanf("%lf",&x[i]);
}
for(int i=;i<=n;i++) {
scanf("%lf",&y[i]);
}
p.push_back(Pt(x[],y[]+));
for(int i=;i<=n;i++) p.push_back(Pt(x[i],y[i]));
p.push_back(Pt(x[n],y[n]+));
for(int i=;i<=n;i++) {
L.push_back(Line(p[i],p[i+]-p[i]));
}
np=HPI(L);
double ans=1e30;
for(int i=;i<np.size();i++)
for(int j=;j<=n;j++) if(np[i].x>=p[j].x&&np[i].x<=p[j+].x) {
Pt x=Pt(np[i].x,-);
x=LineInter(Line(p[j],p[j+]-p[j]),Line(x,np[i]-x));
ans=min(ans,np[i].y-x.y);
}
for(int i=;i<=n;i++)
for(int j=;j<(int)np.size()-;j++) if(p[i].x>=np[j].x&&p[i].x<=np[j+].x) {
Pt x=Pt(p[i].x,-);
x=LineInter(Line(np[j],np[j+]-np[j]),Line(x,p[i]-x));
ans=min(ans,x.y-p[i].y);
}
printf("%.3lf",ans);
return ;
}
bzoj 1038 [ZJOI2008]瞭望塔(半平面交)的更多相关文章
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
1038: [ZJOI2008]瞭望塔 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2999 Solved: 1227[Submit][Statu ...
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
题目大意及模拟退火题解:见 http://blog.csdn.net/popoqqq/article/details/39340759 这次用半平面交写了一遍--求出半平面交之后.枚举原图和半平面交的 ...
- 【BZOJ 1038】 1038: [ZJOI2008]瞭望塔
1038: [ZJOI2008]瞭望塔 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 ...
- bzoj 1038 瞭望塔 半平面交+分段函数
题目大意 给你一座山,山的形状在二维平面上为折线 给出\((x_1,y_1),(x_2,y_2)...(x_n,y_n)\)表示山的边界点或转折点 现在要在\([x_1,x_n]\)(闭区间)中选择一 ...
- 「BZOJ1038」「洛谷P2600」「ZJOI2008」瞭望塔 半平面交+贪心
题目链接 BZOJ/洛谷 题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示: 我们可以用一条山的上方 ...
- 【BZOJ】1038: [ZJOI2008]瞭望塔
http://www.lydsy.com/JudgeOnline/problem.php?id=1038 题意:给出n个x轴各不相同的二维整点,且升序,n<=300,坐标绝对值<=10^6 ...
- 1038: [ZJOI2008]瞭望塔 - BZOJ
Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, ...
- 1038: [ZJOI2008]瞭望塔
半平面交. 半平面指的就是一条直线的左面(也不知道对不对) 半平面交就是指很多半平面的公共部分. 这道题的解一定在各条直线的半平面交中. 而且瞭望塔只可能在各个点或者半平面交折线的拐点处. 求出半平面 ...
- bzoj千题计划126:bzoj1038: [ZJOI2008]瞭望塔
http://www.lydsy.com/JudgeOnline/problem.php?id=1038 本题可以使用三分法 将点按横坐标排好序后 对于任意相邻两个点连成的线段,瞭望塔的高度 是单峰函 ...
随机推荐
- PhoneGap 3.0 官方 安装 方法
为使用最新版本PhoneGap ,决定使用官方提供的方法安装一次. 官方提供方法有些地方没有提到,因此这里记录完整的安装过程: 0.下载java sdk 1.6以上版本 1.下载Android Dev ...
- POJ-1088 滑雪 (包含部分自用测试数据)
这题最简单的想法是深搜+记录,由于数据量比较小.这么做可以AC.如果在h大的情况下这种递归方法总会有一些问题. 如果转换一下,这个可以使用递推来解决,先对高度进行由低到高的排序,然后顺序对这些高度计算 ...
- Spring MVC Checkbox And Checkboxes Example
In Spring MVC, <form:checkbox /> is used to render a HTML checkbox field, the checkbox values ...
- linux2.6中的工作队列接口 workqueue_struct
http://blog.csdn.net/sfrysh/article/details/5801786 工作队列接口 工作队列接口是在2.5的开发过程中引入的,用于取代任务队列接口(用于调 度内核任务 ...
- Android:为控件绑定监听器
为控件绑定监听器主要分为以下步骤: 1.获取代表控件的对象2.定义一个类,实现监听器接口3.生成监听器对象4.为控件绑定监听器对象 实例:Button按钮----监听器OnClickListener ...
- Android 如何动态改变Actionbar上的item图标
1.Activity菜单机制 (与dialog类似) Activity有一套机制来实现对菜单的管理,方法如下: 1.public boolean onCreateOptionsMenu(Menu me ...
- ruby中Block, Proc 和 Lambda 浅析
Block 与Proc的区别: Block是代码块,Proc是对象: 参数列表中最多只能有一个Block, 但是可以有多个Proc或Lambda; Block可以看成是Proc的一个类实例. Proc ...
- ListView使用CursorAdapter增加和删除item
@Override protected void onCreate(Bundle savedInstanceState) { // TODO 自动生成的方法存根 super.onCreate(save ...
- poj 2299 Ultra-QuickSort (归并排序 求逆序数)
题目:http://poj.org/problem?id=2299 这个题目实际就是求逆序数,注意 long long 上白书上的模板 #include <iostream> #inclu ...
- 函数buf_LRU_search_and_free_block
/******************************************************************//** Try to free a replaceable bl ...