BZOJ 1094 ZJOI2007 粒子运动 计算几何

题目大意:给定一个圆,一堆粒子在里面反射,每个粒子只能撞墙k次,求全程粒子间距离的最小值

每两个粒子之间计算一遍

反射就是把射线沿着切线作镜像变换

随便搞搞咯……

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define M 110
#define EPS 1e-7
#define INF 1e9
using namespace std;
typedef long double ld;
struct Point{
	ld x,y;
	Point() {}
	Point(ld _,ld __):
		x(_),y(__) {}
	friend istream& operator >> (istream &_,Point &p)
	{
		_>>p.x>>p.y;
		return _;
	}
	friend Point operator + (const Point &p1,const Point &p2)
	{
		return Point(p1.x+p2.x,p1.y+p2.y);
	}
	friend Point operator - (const Point &p1,const Point &p2)
	{
		return Point(p1.x-p2.x,p1.y-p2.y);
	}
	friend ld operator * (const Point &p1,const Point &p2)
	{
		return p1.x*p2.y-p1.y*p2.x;
	}
	friend Point operator * (const Point &p,ld rate)
	{
		return Point(p.x*rate,p.y*rate);
	}
	friend ld Distance(const Point &p1,const Point &p2)
	{
		return sqrt( (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y) );
	}
}O;
struct Line{
	Point p,v;
	Line() {}
	Line(const Point &_,const Point &__):
		p(_),v(__) {}
	friend istream& operator >> (istream &_,Line &l)
	{
		cin>>l.p>>l.v;
		return _;
	}
	friend Point Get_Intersection(const Line &l1,const Line &l2)//计算两条直线的交点
	{
		Point u=l1.p-l2.p;
		ld temp=(l2.v*u)/(l1.v*l2.v);
		return l1.p+l1.v*temp;
	}
}a[M][M];
int n,k;
ld r,ans=INF;
ld t[M][M];
ld Quadratic_Equation(ld a,ld b,ld c)//解一元二次方程
{
	ld re1=( -b+sqrt(b*b-4*a*c) )/2/a;
	ld re2=( -b-sqrt(b*b-4*a*c) )/2/a;
	return max(re1,re2);
}
ld Get_Intersection(const Line &l)//计算直线与圆的交点
{
	return Quadratic_Equation(	l.v.x*l.v.x+l.v.y*l.v.y,
								2*(l.p.x*l.v.x+l.p.y*l.v.y),
								l.p.x*l.p.x+l.p.y*l.p.y-r*r 	);
}
Point Mirror(const Point &p,const Line &l)//求点p关于直线l的镜像
{
	Point u=Point(l.v.y,-l.v.x);
	Point intersection=Get_Intersection(Line(p,u),l);
	return intersection+(intersection-p);
}
ld Min_Distance(const Line &l1,const Line &l2,ld l,ld r)
{
	ld a=(l1.v.x-l2.v.x)*(l1.v.x-l2.v.x)+(l1.v.y-l2.v.y)*(l1.v.y-l2.v.y);
	ld b=(l1.p.x-l2.p.x)*(l1.v.x-l2.v.x)+(l1.p.y-l2.p.y)*(l1.v.y-l2.v.y);
	if(a<EPS) return Distance(l1.p+l1.v*r,l2.p+l2.v*r);
	ld t=-b/a;
	if(t>r) t=r;
	if(t<l) t=l;
	return Distance(l1.p+l1.v*t,l2.p+l2.v*t);
}
void Calculate(int x,int y)
{
	int i=1,j=1;
	ld last=0;
	while(i<=k&&j<=k)
	{
		if(t[x][i]>t[y][j])
			swap(x,y),swap(i,j);
		ans=min(ans,Min_Distance(a[x][i],a[y][j],last,t[x][i]) );
		last=t[x][i];i++;
	}
}
int main()
{
	int i,j;
	cin>>O>>r>>n>>k;
	for(i=1;i<=n;i++)
	{
		cin>>a[i][1];
		a[i][1].p=a[i][1].p-O;
		for(j=2;j<=k;j++)
		{
			t[i][j-1]=Get_Intersection(a[i][j-1]);
			Point intersection=a[i][j-1].p+a[i][j-1].v*t[i][j-1];
			Point intersection_T=Point(intersection.y,-intersection.x);
			a[i][j]=Line( 	Mirror(a[i][j-1].p,Line(intersection,intersection_T)) ,
							Mirror(a[i][j-1].v,Line(Point(0,0),intersection_T)) ) ;
		}
		t[i][k]=Get_Intersection(a[i][k]);
	}
	for(i=1;i<=n;i++)
		for(j=i+1;j<=n;j++)
			Calculate(i,j);
	cout<<fixed<<setprecision(3)<<ans<<endl;
	return 0;
}
时间: 2024-10-12 23:23:32

BZOJ 1094 ZJOI2007 粒子运动 计算几何的相关文章

bzoj 1059: [ZJOI2007]矩阵游戏 二分图匹配

1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1891  Solved: 919[Submit][Status] Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种操作:行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵

斜率优化专题5——bzoj 1096 [ZJOI2007]仓库建设 题解

[原题] 1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1998  Solved: 816 [Submit][Status] Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场暴雨,于是L先生决

bzoj P1058 [ZJOI2007]报表统计——solution

1058: [ZJOI2007]报表统计 Time Limit: 15 Sec  Memory Limit: 162 MB Submit: 4099  Solved: 1390 [Submit][Status][Discuss] Description 小Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工 作,作为她的生日礼物之一.经过仔细观察,小Q发现统计一张报表实际上是维护一个可能为负数的整数数列,并 且进行一些查询操作.在最开始的时候,有一个长

[BZOJ 1058][ZJOI2007]报表统计

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1058 题解 方法一:离线+离散化+线段树. 这个方式的常数太大,会T.我在洛谷跑最后两个点TLE了,在BZOJRE了. 具体说一下怎么做吧.首先把所有数离散化,把出现过的绝对值离散化.这样我们就能得到约n+m个数和n+m个绝对值.然后,维护两颗线段树,记录数据是否出现,并记录区间出现的最大值和最小值(因为在线段树上的点是从大到小的,假设我们添加了元素k,然后我们找它的数据排位(下标)),每添

BZOJ 1093 [ZJOI2007]最大半连通子图

题意:一个有向图中,若对于任意两个点s和t,要么存在一条从s到t的路径,要么存在一条t到s的路径(当然两条路径都存在也是可以的),那么称这个有向图是一个半联通图.现在给定一个有向图,求出该有向图中点数最多的半联通子图的点数以及个数. 很显然,在一个最优方案中,同一个强连通分量中的点要么都选,要么都不选. 很自然地,先用tarjan缩个点,得到一个有向无环图,每个点的点权为对应的强连通分量的点的个数. 然后稍微脑补一下,就知道第一问的答案显然是该有向无环图上最长链的长度,而第二问的答案自然也就是最

BZOJ 1060: [ZJOI2007]时态同步 树形DP

1060: [ZJOI2007]时态同步 Description 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字1,2,3….进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路板的任何两个节点,都存在且仅存在一条通路(通路指连接两个元件的导线序列).在电路板上存在一个特殊的元件称为“激发器”.当激发器工作后,产生一个激励电流,通过导线传向每一个它所连接的节点.而中间节点接收到激励电流后,得到信息,并将该激励电流传向与它连接并且尚未接

BZOJ 1096: [ZJOI2007]仓库建设( dp + 斜率优化 )

dp(v) = min(dp(p)+cost(p,v))+C(v) 设sum(v) = ∑pi(1≤i≤v), cnt(v) = ∑pi*xi(1≤i≤v), 则cost(p,v) = x(v)*(sum(v)-sum(p)) - (cnt(v)-cnt(p)) 假设dp(v)由dp(i)转移比dp(j)转移优(i>j), 那么  dp(i)+cost(i,v) < dp(j)+cost(j,v) 即 dp(i)+x(v)*(sum(v)-sum(i))-(cnt(v)-cnt(i)) <

BZOJ 1096 [ZJOI2007]仓库建设 斜率优化dp

1096: [ZJOI2007]仓库建设 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1096 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场

BZOJ 1057: [ZJOI2007]棋盘制作 悬线法求最大子矩阵+dp

1057: [ZJOI2007]棋盘制作 Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳.而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则.小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一.小Q想在这种纸中裁减