题意:

一个长宽是100000单位的球场上有很多暴动的观众,每个观众都有一个速度v,

在一秒内,观众会等概率地移动到与原位置的曼哈顿距离<=v的地方(不会移动到界外)。

你需要选取三个位置,这三个位置要求满足在一秒之后可能会出现观众。

(这里不需要考虑概率大小,只要概率不为0就是满足的)

然后过这三点作圆,请选取在初始状态一秒后圆内观众数的期望值最大的方案输出。

如果有多种,输出半径最大的方案。

题解:

第一眼看起来非常可怕…

什么每秒移动速度呀…什么期望呀…先被吓死就做不了了…

其实是假装要扯上概率…

稍微想想就可以发现,总会有一种方案把全部可能位置覆盖…

考虑所有可能位置的点集的凸包,把凸包上的点逐个加入图中并维护一个圆,

假如现在圆上已经存在三个点,正要加入下一个点,

那么如果下一个点在圆内,则不用作任何改动就能保证圆包含所有点,

如果下一个点在圆外,则那个点一定在新的圆上,

那么考虑原来的三个点中让两个不动,那么这两点连线的垂直平分线不动。

那么因为新的圆半径要增大,所以这两个不动的点与圆心的距离(就是半径)会变大,

所以导致圆心在这条垂直平分线上移动时朝着远离这两个点的方向移动…

这时考虑不动的两点中的一个和原来的任意一个点以及圆心构成的三角形,

把这个三角形的边和新旧圆心连起来就可以看出三角形的一角增大一角减小,

(动手画一画可以画出一个蝴蝶出来)

可以证明这个三角形中在新圆上的角比不在新圆上的角要小。

(因为这两个角在旧圆中就已经满足小于等于的关系了,现在小的减小大的增大,显然还是满足)

那么根据大角对大边,这个三角形中不在新圆上的角的顶点离圆心的距离小于新圆的半径,

即顶点在圆内。

所以按照这种方法可以保证最后所有点都在圆内。

有了这种保证,期望什么的就不用管了,答案一定是包含所有点的方案…

然后我们需要找到那个包含全部点并且半径最大的方案。

理所当然地可以有一个猜想:答案一定凸包上相邻的三个点,

感觉上是这样的,因为这样圆弧曲率最小,半径最大…

但是我们要证明它。

考虑分两步证明,首先证明可行性,然后证明最优性。

可行性在上面已经证明了,把相邻三个点放进图中,然后逐个把凸包中的点放进去是可行的。

然后是最优性。假设对于所有的最优方案,不满足那三点相邻,

那么根据假设,在某两点之中,一定存在一个点,并且这个点与这两点确定的圆要比当前小。

分析这个点的位置,如果它在当前圆内,那么这个点与旁边两点确定的圆会比当前圆大。

(因为和当前三点相比,其中两点相同,所以一条垂直平分线相同)

(而在当前圆内那一点与两点中一点的连线的垂直平分线与不变的垂直平分线的交点会变远)

(这一点可以用角度大小关系说明)

因为这个点与旁边两点确定的圆会比当前圆大,与假设不符,所以舍去这种情况。

如果它在当前圆外,与当前圆是最优解矛盾(因为有点在圆外就不是可行解),所以也舍去。

如果它在当前圆上,那么这个点和旁边的两点可以组成一个三点相邻的最优方案,也与假设矛盾。

所以假设不成立…所以它的否命题“存在一个最优方案,满足三点相邻”成立。

于是我们有了这题的做法:在凸包上相邻三个点中找出所有可行解,并在里面取最优。

然后问题又来了,我们怎么知道那些是可行解呢?

我们可以证明,半径最大的方案(不一定是三点相邻)一定是最优解。

因为从我们最开始的过程可以看出,把不可行方案变成可行解时半径会增大。

所以如果一个方案的半径已经最大,无法再增大,那么一定是可行解。

同时又因为半径最大,所以是最优解。

反过来,最优解一定是半径最大的方案,否则不满足最优性。

有了这个结论后,我们就可以确定相邻三点确定的圆中的最大的那个就是我们要找的最优解。

因为所有相邻三点中存在一个最优方案,而这个方案同时是半径最大的方案,

所以在相邻三点中找到的半径最大的方案就是一个全局的最优方案。

一句话总结做法就是:求凸包,在相邻三点的方案中找出半径最大的就是答案。

(另外半径的求法可以用正弦定理推,最后结论是r=abc/4S,abc是内接圆边长)

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define sqr(x) ((x)*(x))
#define dist(a,b) (sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)))
using namespace std;
inline int read()
{
int s = ; char c; while((c=getchar())<'0'||c>'9');
do{s=s*+c-'0';}while((c=getchar())>='0'&&c<='9');
return s;
}
typedef long long lint;
const int N = , RN = 1e5;
int n,tot,mi,t;
int cv[N*];
struct vct
{
lint x,y; double ang;
vct(){}
vct(int x,int y):x(x),y(y){};
bool operator == (const vct &b)const{ return x==b.x&&y==b.y; }
}v[N*];
inline lint cross(lint ax,lint ay,lint bx,lint by){ return ax*by-ay*bx; }
void insertvct(int x,int y)
{
int i = ++tot; v[i].x = x, v[i].y = y;
if(v[i].x<v[mi].x||(v[i].x==v[mi].x&&v[i].y<v[mi].y)) mi = i;
}
bool cmp(const vct &a,const vct &b){ if(a.ang!=b.ang) return a.ang<b.ang; return a.x>b.x; }
void make_convex()
{
cv[] = ; int k = ;
while(v[k]==v[]) k++; cv[] = k++;
while(v[k]==v[cv[]]) k++; cv[t=] = k;
v[++tot] = v[];
for(int i=k+;i<=tot;i++)
{
while(t>=&&cross(v[i].x-v[cv[t]].x,v[i].y-v[cv[t]].y,
v[cv[t]].x-v[cv[t-]].x,v[cv[t]].y-v[cv[t-]].y)>=) t--;
cv[++t] = i;
}
t--;
}
inline double getr(const vct &a,const vct &b,const vct &c)
{
double aa = dist(a,b), bb = dist(b,c), cc = dist(c,a);
double ss = 2.0*abs(cross(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y));
if(ss<=1e-10) return ;
return aa*bb*cc/ss;
}
int main()
{
int i,j,aa,bb,cc;
n = read(), mi = ;
for(i=;i<=n;i++)
{
aa = read(), bb = read(); cc = read();
if(aa-cc>=) insertvct(aa-cc,bb);
else insertvct(,min(RN,bb+cc-aa)), insertvct(,max(,bb-cc+aa));
if(aa+cc<=RN) insertvct(aa+cc,bb);
else insertvct(RN,min(RN,bb+cc-(RN-aa))), insertvct(RN,max(,bb-cc+(RN-aa)));
if(bb-cc>=) insertvct(aa,bb-cc);
else insertvct(min(RN,aa+cc-bb),), insertvct(max(,aa-cc+bb),);
if(bb+cc<=RN) insertvct(aa,bb+cc);
else insertvct(min(RN,aa+cc-(RN-bb)),RN), insertvct(max(,aa-cc+(RN-bb)),RN);
}
swap(v[],v[mi]);
for(i=;i<=tot;i++) v[i].ang = atan2(v[i].y-v[].y,v[i].x-v[].x);
sort(v+,v++tot,cmp);
make_convex();
double mx = getr(v[cv[t]],v[cv[]],v[cv[]]), tmp; int a1 = t, a2 = , a3 = ;
if((tmp=getr(v[cv[t-]],v[cv[t]],v[cv[]]))>mx) a1 = t-, a2 = t, a3 = , mx = tmp;
for(i=;i<=t;i++)
if((tmp=getr(v[cv[i-]],v[cv[i-]],v[cv[i]]))>mx)
a3 = i, mx = tmp;
if(a3>=) a1 = a3-, a2 = a3-;
printf("%I64d %I64d\n%I64d %I64d\n%I64d %I64d\n",
v[cv[a1]].x,v[cv[a1]].y,v[cv[a2]].x,v[cv[a2]].y,v[cv[a3]].x,v[cv[a3]].y);
return ;
}

Bubble Cup 8 finals E. Spectator Riots (575E)的更多相关文章

  1. Bubble Cup 12 - Finals Online Mirror, unrated, Div. 1

    Bubble Cup 12 - Finals Online Mirror, unrated, Div. 1 C. Jumping Transformers 我会状压 DP! 用 \(dp[x][y][ ...

  2. Bubble Cup 11 - Finals [Online Mirror, Div. 1]题解 【待补】

    Bubble Cup 11 - Finals [Online Mirror, Div. 1] 一场很好玩的题啊! I. Palindrome Pairs 枚举哪种字符出现奇数次. G. AI robo ...

  3. Bubble Cup 8 finals I. Robots protection (575I)

    题意: 有一个正方形区域, 要求支持两个操作: 1.放置三角形,给定放置方向(有4个方向,直角边与坐标轴平行),直角顶点坐标,边长 2.查询一个点被覆盖了多少次 1<=正方形区域边长n<= ...

  4. Bubble Cup 8 finals H. Bots (575H)

    题意: 简单来说就是生成一棵树,要求根到每个叶子节点上的路径颜色排列不同, 且每条根到叶子的路径恰有n条蓝边和n条红边. 求生成的树的节点个数. 1<=n<=10^6 题解: 简单计数. ...

  5. Bubble Cup 8 finals G. Run for beer (575G)

    题意: 给定一个带权无向图,每条边的代价为边权/当前速度,每次到达一个新节点,速度都会除以10. 求0号点到n-1号点的最小代价,如果多解输出点数最少的解,输出代价.路径点数.路径经过的点. 1< ...

  6. Bubble Cup 8 finals F. Bulbo (575F)

    题意: 给定初始位置,查询n次区间,每次查询前可以花费移动距离的代价来移动, 查询时需要花费当前位置到区间内最近的点的距离,求最小代价. 1<=n<=5000,1<=所有位置< ...

  7. Bubble Cup 8 finals D. Tablecity (575D)

    题意: (无输入,纯输出题) 一个城市用1000列2行的格子表示,一个小偷藏在城市的某一处. 在每一小时的开始, 在(X, Y)位置的小偷可以移动到 (X - 1, Y), (X + 1, Y),(X ...

  8. Bubble Cup 8 finals C. Party (575C)

    题意: 给定n个人,分两天晚上去夜总会开派对,要求每天恰好有n/2个人去,且每人去的夜总会各不相同. 每个人对不同的晚上不同的夜总会有不同的满意度,求一个方案使得所有人的满意度之和最大. 夜总会数量= ...

  9. Bubble Cup 8 finals B. Bribes (575B)

    题意: 给定一棵n个点和有向边构成的树,其中一些边是合法边,一些边是非法边, 经过非法边需要1的费用,并且经过之后费用翻倍. 给定一个长为m的序列,问从点1开始按顺序移动到序列中对应点的总费用. 1& ...

随机推荐

  1. C#语言基础——函数

    函数一个较大的程序一般应分为若干个程序块,每一个模块用来实现一个特定的功能.所有的高级语言中都有子程序这个概念,用子程序实现模块的功能.在C#语言中,子程序的作用是由一个主函数和若干个函数构成.由主函 ...

  2. 由一个bug引发的SQLite缓存一致性探索

    问题 我们在生产环境中使用SQLite时中发现建表报“table xxx already exists”错误,但DB文件中并没有该表.后面才发现这个是SQLite在实现过程中的一个bug,而这个bug ...

  3. ubuntu kylin 14.04安装搜狗输入法

    1.卸载原有的输入法,fcitx或ibus.如卸载fcitx: sudo apt-get remove fcitx*(如不需保留配置文件用purge) sudo apt-get autoremove( ...

  4. Visual Studio Emulator for Android 初体验

    Visual Studio Emulator for Android已经推出一段时间了,但一直没有用过.前两天下载安装用了下,整体感觉比谷歌自带的模拟器强多了.Visual Studio Emulat ...

  5. Azure上的几个坑

    此文用于记录在使用Azure中国版时遇到的一些“坑”. 1.虚拟机备份/还原 在某些场景中,使用备份/还原功能来创建(克隆)虚拟机比使用capture的image要方便很多.虚拟机备份后,执行还原操作 ...

  6. My first win32 application program

    #include<afxwin.h>#include<afx.h>#define _AFXDLLclass CHelloApp :public CWinApp{public:  ...

  7. 实例:对2个Makefile的备注

    实例1:Makefile编译链接简单.c函数 example.c Makefile exe: example.c gcc example.c -o exe clean: rm exe 执行效果: 实例 ...

  8. 011商城项目:图片服务器的安装---nginx

    这个是电商的项目,不是传统项目,所以给图片单独架一台服务器. 我们看上图: 用户上传图片时上传到Tomcat1或者Tomcat2.然后Tomcat1和Tomcat2通过FTP服务把图片上传到图片服务器 ...

  9. nginx+iis实现负载均衡

    最近在研究分布式系统架构方面的知识,包括负载均衡,数据库读写分离,分布式缓存redis等.本篇先从负载均衡服务架构入手,关于负载均衡百度百科的定义如下:负载均衡,英文名称为Load Balance,其 ...

  10. Java的基本数据类型与转换

    1.1 Java为什么需要保留基本数据类型 http://www.importnew.com/11915.html 基本数据类型对大多数业务相关或网络应用程序没有太大的用处,这些应用一般是采用客户端/ ...