题意:给个最多500 * 500的平面,有半径最多不为1的n个圆,现在给你1e5条线段,问你每条线段和几个圆相交,时限10s

思路:

因为半径<1,那么我其实搜索的范围只要在线段附近就好了。x1 == x2 或者 y1 == y2这个很好理解,不解释。如果是斜率> 0的,那么对于任意的x (x1 <=  x < x2),那我的范围就是floor(yi)~ceil(yi+1),另一种斜率同理。然后我去数每一个格子有没有圆,能不能碰到我线段就行了。每个格子数完标记一下。可以偷个懒,标记为p,然后每次判是不是p,这样就省了每次都初始化。

题解虽然说最好规避sqrt,不过好像精度影响不大。

毒瘤的是输入,x1 > x2,y1 > y2。

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 500 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
double r[maxn][maxn], k;
int vis[maxn][maxn];
double a, b;
double getY(double x){
return k * (x - a) + b;
}
bool check(double x, double y, double R){
double dis = fabs(k * x - k * a + b - y) / sqrt(k * k + 1);
if(dis <= R) return true;
return false;
}
int main(){
int n;
int x1, y1, x2, y2, ans;
memset(r, 0, sizeof(r));
memset(vis, 0, sizeof(vis));
scanf("%d", &n);
for(int i = 1; i <= n; i++){
int u, v;
double l;
scanf("%d%d%lf", &u, &v, &l);
r[u][v] = l;
}
scanf("%d", &n);
for(int p = 1; p <= n; p++){
int up, down;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
a = x1, b = y1;
ans = 0;
k = ((double)(y2 - y1)) / ((double)(x2 - x1));
if(x1 == x2){
if(y1 > y2) swap(y1, y2);
for(int i = y1; i <= y2; i++)
if(r[x1][i] != 0) ans++;
}
else if(y1 == y2){
if(x1 > x2) swap(x1, x2);
for(int i = x1; i <= x2; i++)
if(r[i][y1] != 0) ans++;
}
else{
if(x1 > x2){
swap(x1, x2);
swap(y1, y2);
}
if(k > 0){
for(int i = x1; i < x2; i++){
up = (int)ceil(getY(i + 1));
down = (int)floor(getY(i));
if(i == x1) down = y1;
if(i == x2 - 1) up = y2;
for(int j = down; j <= up; j++){
if(r[i][j] > 0 && vis[i][j] != p && check(i, j, r[i][j])){
vis[i][j] = p;
ans++;
}
if(r[i + 1][j] > 0 && vis[i + 1][j] != p && check(i + 1, j, r[i + 1][j])){
vis[i + 1][j] = p;
ans++;
}
} }
}
else{
for(int i = x1; i < x2; i++){
up = (int)ceil(getY(i));
down = (int)floor(getY(i + 1));
if(i == x1) up = y1;
if(i == x2 - 1) down = y2;
for(int j = down; j <= up; j++){
if(r[i][j] > 0 && vis[i][j] != p && check(i, j, r[i][j])){
vis[i][j] = p;
ans++;
}
if(r[i + 1][j] > 0 && vis[i + 1][j] != p && check(i + 1, j, r[i + 1][j])){
vis[i + 1][j] = p;
ans++;
}
} }
}
}
printf("%d\n", ans);
}
return 0;
}

最新文章

  1. Atitit learn by need 需要的时候学与预先学习知识图谱路线图
  2. EQueue - 一个C#写的开源分布式消息队列的总体介绍
  3. ACM ICPC 2015 Moscow Subregional Russia, Moscow, Dolgoprudny, October, 18, 2015 D. Delay Time
  4. javaIO(三)
  5. SpriteKit
  6. 访何红辉:谈谈Android源码中的设计模式
  7. 一个不错的windows编程网址
  8. (转载)Oracle10g 数据泵导出命令 expdp 使用总结(三)
  9. 201521123029《Java程序设计》第14周学习总结
  10. C#调用RESTful API
  11. R语言学习 第九篇:plyr包
  12. Java基础系列--05_面向对象
  13. AssemblyInfo.cs文件详解
  14. Windows:添加、删除和修改静态路由
  15. ABC2
  16. webSocket+HeadBeat
  17. Apache服务器下phalcon项目报Mod-Rewrite is not enabled问题
  18. Http协议基础知识
  19. Eclipse无法自动编译生成class文件
  20. raft 论文

热门文章

  1. 如何在 Blazor WebAssembly中 使用 功能开关
  2. HTTP Keep-Alive模式客户端与服务器如何判定传输完成
  3. 目标检测的评价指标(TP、TN、FP、FN、Precision、Recall、IoU、mIoU、AP、mAP)
  4. uni-app开发经验分享五: 解决三端页面兼容问题的方法
  5. SpringBoot深入理解
  6. LeetCode上并发题目无Go版本:台湾同胞试水 — 交替打印FooBar
  7. 洛谷P3833
  8. LOJ10160周年纪念晚会
  9. 四:Spring Security 登录使用 JSON 格式数据
  10. Tomcat Servlet工作原理