[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. vue.js 组件-全局组件和局部组件

    这两天学习了Vue.js 感觉组件这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记. 首先Vue组件的使用有3个步骤,创建组件构造器,注册组件,使用组件3个方面. 代码演示如下: <! ...

  2. 关于Ext.js和Ext.Net的杂谈

    最近几年比较火的前端js框架extjs 算是其中的佼佼者.统一的UI设计,强悍的组件及丰富的插件,对浏览器良好的兼容性等优点使得许多公司使用Extjs,同时也使得无数程序猿开始研究这个玩意也包括我在内 ...

  3. MySQL快速生成连续整数

    很多时候需要用到连续的id进行数据对比,如判断是否连续等问题.那么,生成连续整数的方式有多种,首先容易想到的是逐步循环,如果想生成1kw条记录,则需要循环1kw次进行插入,那么有没有其他方式呢,效率相 ...

  4. mysql新增和更新表从已有数据库里面获取的sql语句

    在mysql数据库从已有数据库表插入数据到另一表的sql例子 insert into c(`name`) select name from b; 在mysql数据库从已有数据库表更新数据到另一表的sq ...

  5. Nodejs 使用 SerialPort 调用串口

    工作经常使用串口读写数据,electron 想要替代原来的客户端,串口成了必须要突破的障碍. get -->  https://github.com/EmergingTechnologyAdvi ...

  6. PHP中的mysql_unbuffered_query与mysql_query的区别

    对于mysql_query大家都很熟悉,下面先简单介绍下mysql_unbuffered_query mysql_unbuffered_query (PHP 4 >= 4.0.6, PHP 5) ...

  7. YUM工具使用

    一.yum命令概述: 1.简介: yum命令时在Fedora和RedHat以及SUSE中基于rpm的软件包管理器,它可以使系统管理人员交互和自动化地更细与管理RPM软件包,能够从指定的服务器自动下载R ...

  8. 基于vue来开发一个仿饿了么的外卖商城(二)

    一.抽出头部作为一个组件,在底部导航的时候可以相应的显示不同的标题 技术点:使用slot进行组件间的通信:父组件给子组件传值(子组件里面通过props接收父组件传过来的数据) 查看链接:https:/ ...

  9. Windows Server 2012下手动配置IIS的文件夹访问权限

    当新建一个website的时候,一般情况下IIS对相应的物理文件夹的访问权限是不够的. 针对匿名认证(anonymous authentication)需要: 打开文件夹properties-> ...

  10. AVL重平衡细节——插入

    话说这个系列鸽了好久,之前在准备语言考试,就没管博客了,现在暑假咱们继续上路! 每当我们进行一次插入之后,整棵AVL树的平衡性就有可能发生改变,为了控制整棵树的高度,我们需要通过一系列变换(重平衡)来 ...