BZOJ 1038 ZJOI2008 瞭望塔 模拟退火+二分答案

题目大意:给定一条折线,要求选择一个点建立高度为h的瞭望塔,要求瞭望塔塔顶可以看到折线上的每一个点,求h的最小值

正解:半平面交

不会!

于是我们选择模拟退火来寻找瞭望塔的横坐标

确定瞭望塔的高度的时候我们选择二分处理 对于二分的每一个值 我们把折线上的端点从左到右枚举 瞭望塔的塔尖到每个端点的连线必须从左到右逆时针顺序 否则就会被遮挡

如图,塔尖到点2的连线在到点1的连线的顺时针方向,故点1被遮挡,该高度不可行

写完交上去各种秒WA,最后发现我的INF又不够大。。。我沙茶,我蒟蒻,我这个不长记性的大二货0.0

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 310
using namespace std;
struct point{
	double x,y;
	point(){}
	point(double X,double Y)
	{
		x=X;
		y=Y;
	}
}points[M];
point operator - (const point &x,const point &y)
{
	return point(x.x-y.x,x.y-y.y);
}
double operator * (const point &x,const point &y)
{
	return x.x*y.y-y.x*x.y;
}
struct line{
	point *p1,*p2;
	double k,b;
	void get_function()
	{
		point p=(*p2)-(*p1);
		k=(double)p.y/p.x;
		b=p1->y-k*p1->x;
	}
	double f(double x)
	{
		return k*x+b;
	}
}lines[M];
int n;
double ans,ansheight=1e11;
double Rand()
{
	return rand()%1000/1000.0;
}
bool Judge(point p)
{
	int i;
	for(i=2;i<=n;i++)
	{
		if( (points[i-1]-p)*(points[i]-p)<0 )
			return false;
	}
	return true;
}
double f(double x)
{
	int i;
	for(i=2;i<=n;i++)
		if( x>=lines[i].p1->x && x<=lines[i].p2->x )
			return lines[i].f(x);
}
double Divide(double x)
{
	double l=0,r=1e11;
	double mid=(l+r)/2;
	while(r-l>1e-7)
	{
		if( Judge( point(x,mid) ) )
			r=mid;
		else
			l=mid;
		mid=(l+r)/2;
	}
	mid-=f(x);
	if(mid<ansheight)
		ans=x,ansheight=mid;
	return mid;
}
void SA(double T)
{
	int i;
	double Now=ans;
	for(;T>0.00001;T*=0.99)
	{
		double Neo=Now+T*(Rand()*2-1);
		if( Neo<points[1].x || Neo>points[n].x )
			continue;
		double dE = Divide(Now) - Divide(Neo);
		if( dE>0 || exp(dE/T)>Rand() )
			Now=Neo;
	}
	for(i=1;i<=1000;i++)
	{
		double Neo=ans+T*(Rand()*2-1);
		if( Neo<points[1].x || Neo>points[n].x )
			continue;
		Divide(Neo);
	}
}
int main()
{
	srand(19980406);
	int i;
	cin>>n;
	for(i=1;i<=n;i++)
		scanf("%lf",&points[i].x);
	for(i=1;i<=n;i++)
		scanf("%lf",&points[i].y);
	for(i=2;i<=n;i++)
		lines[i].p1=&points[i-1],lines[i].p2=&points[i],lines[i].get_function();
	ans=(points[n].x+points[1].x)/2.0;
	SA( points[n].x-points[1].x );
	printf("%.3lf\n",ansheight+1e-7);
}
时间: 2024-10-13 11:56:11

BZOJ 1038 ZJOI2008 瞭望塔 模拟退火+二分答案的相关文章

BZOJ 1038 ZJOI2008 瞭望塔 半平面交

题目大意及模拟退火题解:见 http://blog.csdn.net/popoqqq/article/details/39340759 这次用半平面交写了一遍--求出半平面交之后.枚举原图和半平面交的每一个点,求出答案就可以 #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 310 #define

1038: [ZJOI2008]瞭望塔

半平面交. 半平面指的就是一条直线的左面(也不知道对不对) 半平面交就是指很多半平面的公共部分. 这道题的解一定在各条直线的半平面交中. 而且瞭望塔只可能在各个点或者半平面交折线的拐点处. 求出半平面交,枚举即可. #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define eps 1e-7 using namespace std; const int maxn

【BZOJ】1038: [ZJOI2008]瞭望塔

http://www.lydsy.com/JudgeOnline/problem.php?id=1038 题意:给出n个x轴各不相同的整点且升序,n<=300,求这些点依次连接后折线的上面取一个点(x, y)使得:x0<=x<=xn,且这个点可以看得到所有线段的所有点.要求这些点到(垂直到)折线的y值之差最小. #include <cstdio> #include <cstring> #include <cmath> #include <stri

【BZOJ 1038】 [ZJOI2008]瞭望塔

1038: [ZJOI2008]瞭望塔 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 973  Solved: 428 [Submit][Status] Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), -. (xn, yn)来描述H村的形状,这里x1 < x2 <

bzoj千题计划126:bzoj1038: [ZJOI2008]瞭望塔

http://www.lydsy.com/JudgeOnline/problem.php?id=1038 本题可以使用三分法 将点按横坐标排好序后 对于任意相邻两个点连成的线段,瞭望塔的高度 是单峰函数,而且是下凸函数 感性理解单峰就是 瞭望塔建的靠左,为了能看到右边的,要高一点 瞭望塔建的靠右,为了能看到左边的,要高一点 所以 枚举所有线段,三分线段上建造瞭望塔的位置,所有线段上的瞭望塔高度取最小 #include<cmath> #include<cstdio> #include

【BZOJ1038】[ZJOI2008]瞭望塔 半平面交

[BZOJ1038][ZJOI2008]瞭望塔 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn.瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置.可见在不同的位置建造瞭望塔,所需要建造的

【BZOJ1038】【ZJOI2008】瞭望塔 [模拟退火]

瞭望塔 Time Limit: 10 Sec  Memory Limit: 162 MB[Submit][Status][Discuss] Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn. 瞭望塔可以建造在[x1, xn]间的任意

[ZJOI2008]瞭望塔

题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn.瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置.可见在不同的位置建造瞭望塔,所需要建造的高度是不同的.为了节省开支,dadzhi村长希望建造的塔高度

BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )

我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利去check就行了...其实这道题挺好想但是码量还是挺大的.... ----------------------------------------------------------------------------- #include<cstdio> #include<cstring&