[BZOJ4920][Lydsy六月月赛]薄饼切割

试题描述

有一天,tangjz 送给了 quailty 一张薄饼,tangjz 将它放在了水平桌面上,从上面看下去,薄饼形成了一个 \(H \times W\) 的长方形。

tangjz 交给了 quailty 一根木棍,要求 quailty 将木棍轻轻放到桌面上。然后 tangjz 会以薄饼中心作为原点,将木棍绕着原点旋转一圈,将木棍扫过的部分切下来送给 quailty。

quailty 已经放好了木棍,请写一个程序帮助他们计算 quailty 得到了多少面积的薄饼。

输入

第一行包含一个正整数 \(T(1 \le T \le 1000)\),表示测试数据的组数。

每组数据包含一行 \(6\) 个整数 \(H,W,x_1,y_1,x_2,y_2(1 \le H,W \le 10000,|x_1|,|y_1|,|x_2|,|y_2| \le 10000)\),其中 \(H\) 和 \(W\) 表示薄饼的长和宽,\((x_1,y_1)\) 和 \((x_2,y_2)\) 分别表示木棍两端点的坐标。

输入数据保证木棍两端点不会重合。

输出

对于每组数据,输出一行一个实数,即 quailty 得到的面积,与标准答案的绝对或相对误差不超过 \(10^{-8}\) 时会被认为是正确的。

输入示例

2
3 2 -4 0 -4 -3
1 5 -4 -3 4 2

输出示例

0.0000000000000
4.4352192982310

数据规模及约定

见“输入

题解

不难发现扫过的面就是一个大圆和长方形的交减去小圆和长方形的交。

下面令 \(P_1(x_1, y_1), P_2(x_2, y_2)\),\(O\) 为原点。

首先需要确定大圆小圆的半径。大圆的半径就是线段 \(P_1P_2\) 到原点的最大距离,即 \(\max \{ |OP_1|, |OP_2| \}\)。小圆的半径则是线段 \(P_1P_2\) 到原点的最小距离,如果过原点做 \(P_1P_2\) 所在直线的垂线与 \(P_1P_2\) 有交的话(这个可以用向量的点积判断),距离就是这个垂线段的长度,可以直接用面积法计算出来;如果没有交点那就是 \(\min \{ |OP_1|, |OP_2| \}\)。

接下来考虑如何计算一个半径为 \(r\),圆心为 \(O\) 的圆与四个顶点坐标分别为 \(\begin{Bmatrix} \left( -\frac{W}{2}, \frac{H}{2} \right), \left( \frac{W}{2}, \frac{H}{2} \right), \left( \frac{W}{2}, -\frac{H}{2} \right), \left( -\frac{W}{2}, -\frac{H}{2} \right) \end{Bmatrix}\) 的矩形的交集的面积。

这个东西还是分类讨论一下:

  • 如果圆将整个矩形包含(即 \(2r \ge \sqrt{W^2 + H^2}\)),则面积为 \(W \cdot H\);
  • 否则就是一个圆的面积减去几个弓形的面积(注意判断一下是否与上下、左右边界相交),这个弓形的面积就是扇形的面积减去一个三角形的面积,可以利用 acos(x)(即 \(\arccos(x)\))函数得到扇形的角度从而得到扇形面积,用叉积计算三角形的面积。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;
#define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
#define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--) int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} const double pi = acos(-1.0); struct Vec {
double x, y;
Vec() {}
Vec(double _, double __): x(_), y(__) {}
Vec operator - (const Vec& t) const { return Vec(x - t.x, y - t.y); }
double operator * (const Vec& t) const { return x * t.x + y * t.y; }
double operator ^ (const Vec& t) const { return x * t.y - y * t.x; }
double len() { return sqrt(x * x + y * y); }
}; double OutArea(double h, double a) {
double c = sqrt(a * a - h * h), S = pi * a * a * acos(h / a) / pi;
S -= abs(Vec(c, h) ^ Vec(-c, h)) / 2.0;
return S;
}
double Area(double H, double W, double r) {
if(H > W) swap(H, W);
if(r >= sqrt(H * H + W * W) / 2.0) return H * W;
double S = pi * r * r;
if(r > H / 2.0) S -= 2.0 * OutArea(H / 2.0, r);
if(r > W / 2.0) S -= 2.0 * OutArea(W / 2.0, r);
return S;
} double calcDis(Vec p1, Vec p2) {
if(min((p1 - p2) * (Vec(0, 0) - p2), (p2 - p1) * (Vec(0, 0) - p1)) < 0) return min(p1.len(), p2.len());
return abs(p1 ^ p2) / (p1 - p2).len();
} void work() {
int H = read(), W = read(), x1 = read(), y1 = read(), x2 = read(), y2 = read();
double l = calcDis(Vec(x1, y1), Vec(x2, y2)), r = max(Vec(x1, y1).len(), Vec(x2, y2).len());
printf("%.13lf\n", Area(H, W, r) - Area(H, W, l));
return ;
} int main() {
int T = read();
while(T--) work(); return 0;
}

[BZOJ4920][Lydsy六月月赛]薄饼切割的更多相关文章

  1. BZOJ4920: [Lydsy1706月赛]薄饼切割

    BZOJ4920: [Lydsy1706月赛]薄饼切割 Description 有一天,tangjz送给了quailty一张薄饼,tangjz将它放在了水平桌面上,从上面看下去,薄饼形成了一个H*W的 ...

  2. 【BZOJ4919】[Lydsy六月月赛]大根堆 线段树合并

    [BZOJ4919][Lydsy六月月赛]大根堆 Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切 ...

  3. 【BZOJ4922】[Lydsy六月月赛]Karp-de-Chant Number 贪心+动态规划

    [BZOJ4922][Lydsy六月月赛]Karp-de-Chant Number Description 卡常数被称为计算机算法竞赛之中最神奇的一类数字,主要特点集中于令人捉摸不透,有时候会让水平很 ...

  4. bzoj 4921: [Lydsy六月月赛]互质序列

    4921: [Lydsy六月月赛]互质序列 Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 188  Solved: 110[Submit][Status ...

  5. bzoj 4919: [Lydsy六月月赛]大根堆

    Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质: ...

  6. 【BZOJ4919】[Lydsy六月月赛]大根堆

    题解: 我觉得数据结构写成结构体还是有必要的 因为不然一道题里出现了两个相同的数据结构由于名字很像很容易出错 另外初始化用segmenttree(){ } 首先裸的dp很好想 f[i][j]表示在i点 ...

  7. 【bzoj4921】[Lydsy六月月赛]互质序列 暴力

    题目描述 给出一个序列,要求删除一段非空区间,使得剩下的数的个数大于等于2.求所有删除方式剩下的数的最大公约数的和. 输入 第一行包含一个正整数n(3<=n<=100000),表示序列的长 ...

  8. 【bzoj4922】[Lydsy六月月赛]Karp-de-Chant Number 贪心+背包dp

    题目描述 给出 $n$ 个括号序列,从中选出任意个并将它们按照任意顺序连接起来,求以这种方式得到匹配括号序列的最大长度. 输入 第一行包含一个正整数n(1<=n<=300),表示括号序列的 ...

  9. 【BZOJ5072】[Lydsy十月月赛]小A的树 树形DP

    [BZOJ5072][Lydsy十月月赛]小A的树 题解:考虑我们从一个联通块中替换掉一个点,导致黑点数量的变化最多为1.所以我们考虑维护对于所有的x,y的最大值和最小值是多少.如果询问的y在最大值和 ...

随机推荐

  1. Java : 实体类不能序列化异常

    当修改实体类之后调用接口出现不能序列化的异常时,一定要检查实体之间的关系是否都是正确的. could not serialize; nested exception is org.hibernate. ...

  2. JavaSE 第二次学习随笔(二)

    循环结构中的多层嵌套跳出 targeta: for(int i = 0; i < 100; i++){ for (int j = 0; j < 100; j++) { if(i + j = ...

  3. Python学习 :深浅拷贝

    深浅拷贝 一.浅拷贝 只拷贝第一层数据(不可变的数据类型),并创建新的内存空间进行储蓄,例如:字符串.整型.布尔 除了字符串以及整型,复杂的数据类型都使用一个共享的内存空间,例如:列表 列表使用的是同 ...

  4. rails小技巧之分组查询统计并去重

    分组查询并统计 SpecialGroup.group(:special_type).count select special_type,count(*) from special_groups gro ...

  5. List排序方法

    可用使用Collections.sort(List<T> list)和Collections.sort(List<T> list, Comparator<? super ...

  6. 10+ Best Responsive HTML5 AngularJS Templates

    http://www.responsivemiracle.com/collective/best-responsive-html5-angularjs-templates/

  7. 20145202马超 实验二《Java面向对象程序设计》实验报告

    实验二 Java面向对象程序设计 实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装.继承.多态 3.初步掌握UML建模 4.熟悉S.O.L.I.D原则 5.了解设计模式 实验 ...

  8. LARK BOARD开发板试用第一篇-上电测试学习

    1. 先看下板子外观,做工很不错 2. 主芯片的型号是,SoC 为 Cyclone V SX 系列的 5CSXFC6D6F31,不仅在芯片中包含传统的 FPGA 架构,还集成了基于 ARM Corte ...

  9. 【BZOJ 1269】文本编辑器

    题目 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对"文本编辑器"做了一个抽象的定义: Move k:将 ...

  10. 『AngularJS』创建 Service

    创建服务 Angular提供了几种有用的服务,对于所有的应用来说,你将会发现这些服务对于创建你自己的服务是有用处的.为了创建自己的服务,你应该从通过一个模块(module)注册一个服务工厂方法开始(可 ...