当前位置: 首页 > news >正文

UVa1367/LA3532 Nuclear Plants

UVa1367/LA3532 Nuclear Plants

  • 题目链接
  • 题意
  • 分析
  • 测试数据
  • AC 代码

题目链接

  本题是2005年icpc欧洲区域赛中欧赛区的题目

题意

  某国是一个长n公里,宽m公里的矩形,边平行于坐标轴,左上角的坐标为(0,0),右下角的坐标为(n,m)。该国领土上有一些核电厂。核电厂有大小之分,小核电厂周围0.58公里内都不能种植大麦,大核电厂周围1.31公里内都不能种植大麦。你的任务是计算出可以种植大麦的总面积。

分析

  经典题目:求圆的面积并,用离散化扫描法求解,详细思路《算法竞赛入门经典–训练指南》第433页有写,这里只说一些编程细节:
  调用数学运算函数sqrt、acos这种函数时一定要消除数值异常,推荐这样写:sqrt(max(x, 0.)),acos(max(min(x, 1.), -1.))
  计算两圆的交点也要消除数值异常

#define eps 1e-9
double dx = cx2-cx1, dy = cy2-cy1, d = sqr(dx*dx + dy*dy);
if (d > r1+r2-eps || d < eps) return;

  某个扫描段只有一个上/下圆弧时面积的计算要特殊考虑

测试数据

  给一份测试数据。

AC 代码

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;

#define rs .58
#define rl 1.31
#define eps 1e-9
#define M 40200
#define N 102
#define sqr(x) sqrt(max(x, 0.))
#define aco(x) acos(max(min(x, 1.), -1.))
int xs[N], ys[N], xl[N], yl[N], a[N], b[N], m, n, ks, kl, t, c; double x[M];

struct arc {
   int cx, cy; bool s, t; double y;
   double area(double x1, double x2) const {
      double r = s ? rs : rl, dx1 = x1 - cx, dx2 = x2 - cx,
         y1 = cy - sqr(r*r - dx1*dx1), y2 = cy - sqr(r*r - dx2*dx2), dy1 = y1 - cy, dy2 = y2 - cy;
      double t = aco((dx1*dx2+dy1*dy2)/sqr(dx1*dx1+dy1*dy1)/sqr(dx2*dx2+dy2*dy2));
      return .5 * (r*r*t - abs(dx1*dy2-dx2*dy1));
   }
   double yy(double x) const {
      double r = s ? rs : rl, dx = x - cx;
      return t ? cy + sqr(r*r - dx*dx) : cy - sqr(r*r - dx*dx);
   }
   bool operator< (const arc& rhs) const {
      return y < rhs.y;
   }
} q[N<<2];

bool cmps(int i, int j) {
   return xs[i] < xs[j];
}

bool cmpl(int i, int j) {
   return xl[i] < xl[j];
}

void intersect(int cx1, int cy1, int cx2, int cy2, double r1, double r2) {
   double dx = cx2-cx1, dy = cy2-cy1, d = sqr(dx*dx + dy*dy);
   if (d > r1+r2-eps || d < eps) return;
   double d1 = .5 * (d + (r1*r1 - r2*r2)/d), s = sqr(r1*r1-d1*d1), x0 = cx1 + dx*d1/d;
   d = dy*s/d; x[t++] = x0 - d; x[t++] = x0 + d;
}

void intersect(int cx, int cy, double r) {
   if (cy < r) {
      double s = sqr(r*r-cy*cy); x[t++] = cx - s; x[t++] = cx + s;
   }
   if (cy + r > m) {
      double s = sqr(r*r-(m-cy)*(m-cy)); x[t++] = cx - s; x[t++] = cx + s;
   }
}

void add_arc(int cx, int cy, bool s, double x) {
   double r = s ? rs : rl;
   if (abs(x-cx) > r-eps) return;
   double d = sqr(r*r-(x-cx)*(x-cx));
   if (cy > d) q[c++] = {cx, cy, s, false, cy-d};
   if (cy+d < m) q[c++] = {cx, cy, s, true, cy+d};
}

double solve() {
   for (int i=t=0; i<ks; ++i) {
      cin >> xs[i] >> ys[i], x[t++] = xs[i]-rs, x[t++] = xs[i]+rs, a[i] = i, intersect(xs[i], ys[i], rs);
      for (int j=0; j<i; ++j) intersect(xs[i], ys[i], xs[j], ys[j], rs, rs);
   }
   for (int i=0; i<kl; ++i) {
      cin >> xl[i] >> yl[i], x[t++] = xl[i]-rl, x[t++] = xl[i]+rl, b[i] = i, intersect(xl[i], yl[i], rl);
      for (int j=0; j<i; ++j) intersect(xl[i], yl[i], xl[j], yl[j], rl, rl);
      for (int j=0; j<ks; ++j) intersect(xs[j], ys[j], xl[i], yl[i], rs, rl);
   }
   x[t++] = 0.; x[t++] = n; sort(a, a+ks, cmps); sort(b, b+kl, cmpl); sort(x, x+t);
   double s = m*n; int h1 = 0, h2 = 0;
   for (int i=1; i<t; ++i) {
      double x1 = x[i-1], x2 = x[i], xc = .5*(x1+x2); c = 0;
      if (x1 > x2-eps || x1 < -eps || x2 > n+eps) continue;
      while (h1 < ks && xs[a[h1]]+rs < x1-eps) ++h1;
      for (int j=h1; j<ks && xs[a[j]]-rs < x2+eps; ++j) add_arc(xs[a[j]], ys[a[j]], true, xc);
      while (h2 < kl && xl[b[h2]]+rl < x1-eps) ++h2;
      for (int j=h2; j<kl && xl[b[j]]-rl < x2+eps; ++j) add_arc(xl[b[j]], yl[b[j]], false, xc);
      sort(q, q+c);
      for (int j=0, cc=0; j<c; ++j) if (q[j].t) {
         if (cc) {
            if (--cc == 0) s -= q[j].area(x1, x2) + .5*(x2-x1)*(q[j].yy(x1)+q[j].yy(x2));
         } else s -= q[j].area(x1, x2) + .5*(x2-x1)*(q[j].yy(x1)+q[j].yy(x2));
      } else if (++cc == 1) s -= q[j].area(x1, x2) - .5*(x2-x1)*(q[j].yy(x1)+q[j].yy(x2)-(j==c-1 ? 2.*m : 0.));
   }
   return s;
}

int main() {
   cout << fixed << setprecision(2);
   while (cin >> n >> m >> ks >> kl && (n || m || ks || kl)) cout << solve() << endl;
   return 0;
}

相关文章:

  • 第十五届蓝桥杯大赛软件赛省赛Python 大学 B 组试做(下)【本期题单: 缴纳过路费, 纯职业小组】
  • Asp.NET Core WebApi 配置文件
  • 网站集群批量管理-Ansible剧本与变量
  • 什么是生产管理看板?
  • Google Cloud Next 2025大会发布多项重大产品
  • winform读写App.config配置文件
  • 汽车性能的幕后保障:慧通测控电动尾翼综合力学测试浅析
  • c++拷贝构造函数(深浅拷贝)+运算符重载
  • python 语言 设计模式
  • FRP的proxies只是建立通道,相当于建立与服务器沟通的不同通道而不是直接将路由器与服务器云端沟通
  • 深度学习-156-RAG技术之在ubuntu中的安装部署RAGFlow和简单应用
  • 嵌入式---烧录器
  • Vue客服组件集成Dify智能问答:从设计到落地(3)
  • 24.OpenCV中的霍夫直线检测
  • 紧跟政策步伐:道路运输安全员证报名指南​
  • 声学测温度原理解释
  • NeuroImage:膝关节炎如何影响大脑?静态与动态功能网络变化全解析
  • wx213基于php+vue+uniapp的新闻资讯小程序
  • 2025年的Android NDK 快速开发入门
  • cgroups
  • 个人网站可以做淘宝客吗/海淀区seo搜索优化
  • 怎样将自己做的网站发布到外网上/宁波网站建设公司
  • 北京免费发布企业信息网站/广告推广软文案例
  • 招工网站服务/seo人员是什么意思
  • 电子商务网站分析/2022最新国际新闻10条简短
  • 嘉兴高端建站公司/360搜索引擎优化