@codeforces - 575E@ Spectator Riots
@description@
一个以 (0, 0) 为左下角,(10^5, 10^5) 为右上角的球场中有 n 个人,第 i 个人在 (xi, yi) 上,并有速度 vi。
在 1s 后,每个人会等概率地移动到与原位置的曼哈顿距离 <= v 的地方(不会移动到界外)。
你需要选取三个位置(满足这些位置在 1s 后可能出现人),然后过这三点作圆。
请选取在初始状态 1s 后圆内人数的期望值最大的方案输出。如果有多种,输出半径最大的方案。
@solution@
首先根据最小圆覆盖那一套理论(或者你乱猜都猜得到),存在一个圆经过给定点集的三个点,覆盖整个点集。
那么这道题的最大期望值就是骗人的 = =。
我们可以先对原始点集求一个凸包,再在凸包上作圆。
首先注意到,半径最大的圆一定包含整个凸包。否则我可以搞出一个半径更大的圆。
为了分析,我们随便画一个如图的凸包:
再随便钦定两个必须在圆上的点,则圆心在它们的中垂线上移动。随便找一个合适的圆:
注意到此时我可以将圆心上移或者下移,使得凸包与圆相切。
因为圆心向下移动一定会在某刻切中上面的点,向上移动一定会在某刻切中下面的点,所以经过两个点的圆最多出现两种情况。
而根据圆心的位置,上移和下移必然有一个对应半径是单调增大的。
但是假如这两个顶点相邻,则上移和下移中只会有一个情况会切到凸包。
那么假如我选取的圆在凸包上的三个点 A, B, C 不相邻,必然可以从三个点选择两个点 P, Q(只要这两个点之间的边 PQ 对应的角是锐角),使得以 P, Q 作中垂线,把圆心往另一个方向挪,半径会单调增大。
也就是说,这道题求出凸包过后只需要求凸包上三个相邻点对应的半径最大的外切圆 = =。
三角形外切圆的半径可以用正弦公式得到为 \(R = \frac{a*b*c}{4*S}\)。
@accepted code@
#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define border(p) (0 <= p.x && p.x <= 1E5 && 0 <= p.y && p.y <= 1E5)
#define inside(p, v, x) (fabs(x.x - p.x) + fabs(x.y - p.y) <= v)
const int MAXN = int(1E6);
const double INF = 1E10;
const double EPS = 1E-9;
int dcmp(double x) {return fabs(x) <= 0 ? 0 : (x > 0 ? 1 : -1);}
struct point{
double x, y;
point() : x(), y() {}
point(double _x, double _y) : x(_x), y(_y) {}
friend point operator + (point a, point b) {return point(a.x + b.x, a.y + b.y);}
friend point operator - (point a, point b) {return point(a.x - b.x, a.y - b.y);}
friend point operator * (point a, double k) {return point(a.x * k, a.y * k);}
friend point operator / (point a, double k) {return point(a.x / k, a.y / k);}
friend double operator * (point a, point b) {return a.x*b.x + a.y*b.y;}
friend double operator ^ (point a, point b) {return a.x*b.y - a.y*b.x;}
friend bool operator < (point a, point b) {return (a.x == b.x ? a.y < b.y : a.x < b.x);}
friend bool operator == (point a, point b) {return (a.x == b.x) && (a.y == b.y);}
friend double length(point a) {return sqrt(a * a);}
friend double dist(point a, point b) {return length(a - b);}
friend double area(point a, point b, point c) {return ((c - a) ^ (b - a)) / 2;}
friend double slope(point a, point b) {
if( a.x == b.x ) return a.y < b.y ? INF : -INF;
else return 1.0*(a.y - b.y)/(a.x - b.x);
}
friend void read(point &a) {scanf("%lf%lf", &a.x, &a.y);}
};
point stk[MAXN + 5], t[MAXN + 5], a[MAXN + 5];
int siz, cnt, tp;
void convex() {
sort(a + 1, a + cnt + 1);
stk[tp = 1] = a[1];
for(int i=2;i<=cnt;i++) {
if( a[i] == a[i-1] ) continue;
while( tp >= 2 && slope(stk[tp-1], stk[tp]) <= slope(stk[tp], a[i]) )
tp--;
stk[++tp] = a[i];
}
for(int i=1;i<=tp;i++)
t[++siz] = stk[i];
stk[tp = 1] = a[1];
for(int i=2;i<=cnt;i++) {
if( a[i] == a[i-1] ) continue;
while( tp >= 2 && slope(stk[tp-1], stk[tp]) >= slope(stk[tp], a[i]) )
tp--;
stk[++tp] = a[i];
}
for(int i=tp-1;i>=2;i--)
t[++siz] = stk[i];
}
int nxt(int x) {return (x == siz ? 1 : x + 1);}
void print(point p) {printf("%.0f %.0f\n", p.x, p.y);}
void solve() {
convex();
double r = 0; int p = 0;
for(int i=1;i<=siz;i++) {
int j = nxt(i), k = nxt(j);
double r1 = dist(t[i],t[j])*dist(t[i],t[k])*dist(t[j],t[k])/(4*area(t[i],t[j],t[k]));
if( dcmp(r1 - r) > 0 ) p = i, r = r1;
}
print(t[p]), p = nxt(p);
print(t[p]), p = nxt(p);
print(t[p]), p = nxt(p);
}
void update1(point p) {
if( border(p) ) a[++cnt] = p;
}
void update2(point p, double v, point x) {
if( inside(p, v, x) ) a[++cnt] = x;
}
int main() {
int n; scanf("%d", &n);
for(int i=1;i<=n;i++) {
double x, y, v; scanf("%lf%lf%lf", &x, &y, &v);
point p = point(x, y);
update1(point(x + v, y)), update1(point(x - v, y));
update1(point(x, y + v)), update1(point(x, y - v));
if( x - v < 0 ) update1(point(0, y + (v - x))), update1(point(0, y - (v - x)));
if( y - v < 0 ) update1(point(x + (v - y), 0)), update1(point(x - (v - y), 0));
if( x + v > 1E5 ) update1(point(1E5, y + (v - (1E5 - x)))), update1(point(1E5, y - (v - (1E5 - x))));
if( y + v > 1E5 ) update1(point(x + (v - (1E5 - y)), 1E5)), update1(point(x - (v - (1E5 - y)), 1E5));
update2(p, v, point(0, 0)), update2(p, v, point(1E5, 1E5));
update2(p, v, point(0, 1E5)), update2(p, v, point(1E5, 0));
}
solve();
}
@details@
注意一下凸包上可能会有重合 / 共线的点,都要排除掉。
求凸包之间涉及到求两个凸多边形的交(对应不能跑出界限),看上去要半平面交,实际上把所有可能的点求出来暴力判是否在两个多边形内就可以了。
@codeforces - 575E@ Spectator Riots的更多相关文章
- Bubble Cup 8 finals E. Spectator Riots (575E)
题意: 一个长宽是100000单位的球场上有很多暴动的观众,每个观众都有一个速度v, 在一秒内,观众会等概率地移动到与原位置的曼哈顿距离<=v的地方(不会移动到界外). 你需要选取三个位置,这三 ...
- 【Codeforces Round】 #432 (Div. 2) 题解
Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017) A. Arpa and a research in Mexi ...
- Codeforces 581F Zublicanes and Mumocrates - 树形动态规划
It's election time in Berland. The favorites are of course parties of zublicanes and mumocrates. The ...
- Codeforces 788A Functions again - 贪心
Something happened in Uzhlyandia again... There are riots on the streets... Famous Uzhlyandian super ...
- codeforces 407 div1 A题(Functions again)
codeforces 407 div1 A题(Functions again) Something happened in Uzhlyandia again... There are riots on ...
- python爬虫学习(5) —— 扒一下codeforces题面
上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...
- 【Codeforces 738D】Sea Battle(贪心)
http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...
- 【Codeforces 738C】Road to Cinema
http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...
- 【Codeforces 738A】Interview with Oleg
http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...
随机推荐
- python3.x 基础七:面向对象进阶
类的高级方法: 1.静态方法:在类方法前增加关键字@staticmethod,将普通方法变成静态方法,不能再次传值,不能访问实例变量或者类变量,与类的关系仅仅是通过类名进行调用 2.类方法:在类方法前 ...
- Fabric进阶(一)—— 修改组织和通道的名称
组织(Org)和通道(Channel)的名称是fabric网络比较重要的两个配置参数,在fabric提供的示例中都已经设置好了这两个参数,一般组织名为"Org1"和"Or ...
- VueCli4构建项目如何配置文件路径别名?
1.在项目文件根目录上创建 vue.config.js 文件 2.写入以下代码,具体内容见注释: const path = require('path') // 引入path模块 function r ...
- 已解决[Authentication failed for token submission,Illegal hexadecimal charcter s at index 1]
在初次学习使用shiro框架的时候碰到了这个问题,具体报错情况如下: [org.apache.shiro.authc.AbstractAuthenticator] - Authentication f ...
- JAVA-Servlet操纵方法
此篇自用查询 存储数据的区域对象域对象的通用的方法:ServletContext context=getServletContext();获取ServletContext对象setAtrribute( ...
- ORCLE 列转行
字符串转多列 实际上就是拆分字符串的问题,可以使用 substr.instr.regexp_substr函数方式 字符串转多行 使用union all函数等方式 wm_concat函数 wm_conc ...
- javascript 循环中调用异步的同步需求
// 关于Promise:可以直接使用promise Promise.resolve(123).then(v => { console.log(v) }) // 循环中调用异步 let arr ...
- Java Spring Cloud 实战之路 - 1 创建项目
0. 前言 该项目使用Maven进行管理和构建,所以需要预先配置好Maven.嗯,在这个系列里就不做过多的介绍了. 1. 创建项目 先创建一个pom.xml 文件,添加以下内容: <?xml v ...
- kali下安装beef并联合Metasploit
安装beef 在kali中安装beef比较容易,一条命令就可以安装了,打开终端,输入apt-get install beef-xss ,安装前可以先更新一下软件apt-get update 修改bee ...
- zabbix通过IPMI模式监控服务器风扇转速和温度反映机房室温变化实例
说明:2019年4月7日321机房OA服务器主板监控风扇转速和温度有明显升高,其后3天呈逐日升高趋势.检查机房感觉空调制冷量不足.4月11日联系空调维修进行处理,空调制冷恢复正常,风扇转速和温度监 ...