计算几何练习

以前基本没有做过计算几何, 为了练习, 现在做了几道。

 

 3630: [JLOI2014]镜面通道

 

题目大意:给定一个二维的通道,通道内有一些正方形和圆形的零件(允许重叠),求最少删掉多少零件可以使光线通过反射通过这个通道

 

首先我们大概可以感知到只要通道的两端是联通的就一定可以有一种可行方案 (想了想并不会证,,似乎有一个什么定理?)

然后不就是一个简单最小割了吗,,,通道的上面是S, 下面是T,两个元素相交的话就连一条边。就好了。

于是现在是一个判断 两个圆之间, 两个矩形之间, 一个圆和一个矩形之间 是否相交的问题。

两个圆很好判,有矩形的话因为这道题中所有的矩形都是平行于坐标轴的所以只有四个顶点是关键点, 圆也只有最上面最下面最左面最右面四个点是关键点,然后枚举一下随便判一判就好啦,,感觉很不优美。

 

 

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <queue>
  7  #define MAXN 1005
  8  #define INF 1<<29
  9  #define T 2*n+1
 10  #define fi 2*i-1
 11  #define si 2*i
 12  #define fj 2*j-1
 13  #define sj 2*j
 14  using  namespace std;
 15  int X, Y, n, head[MAXN], ee = - 1, dis[MAXN];
 16  struct point{
 17      int kk, x1, y1, r1, x2, y2;
 18 }p[MAXN];
 19  struct Edge{
 20      int to, next, f;
 21 }edge[ 5000005];
 22 inline  void addedge( int x,  int y,  int f){ // printf("!! %d %d %d\n", x, y, f);
 23 edge[++ ee].to = y; edge[ee].f = f; edge[ee].next = head[x]; head[x] = ee;}
 24 inline  double dist( int x1,  int y1,  int x2,  int y2){ return sqrt(( double)((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)));}
 25 inline  void Add( int i,  int j){ // printf("***** %d %d\n", i, j); 
 26 addedge(si, fj, INF); addedge(fj, si,  0); addedge(sj, fi, INF); addedge(fi, sj,  0);}
 27  bool inz( int x,  int y,  int i){
 28      if(x >= p[i].x1 && x <= p[i].x2 && y >= p[i].y1 && y <= p[i].y2)  return  1return  0;
 29 }
 30  int q[ 1000005];
 31  bool bfs(){
 32      for( int i =  0; i <= T; i ++) dis[i] = - 1;
 33      int hh =  0, tt =  1;
 34     dis[ 0] =  1; q[ 0] =  0;
 35      while(hh != tt){
 36          int u = q[hh ++];
 37          for( int i = head[u]; i != - 1; i = edge[i].next)  if(dis[edge[i].to] == - 1 && edge[i].f){
 38             dis[edge[i].to] = dis[u] +  1;
 39             q[tt ++] = edge[i].to;
 40              if(edge[i].to == T) return  1;
 41         }
 42     } return  0;
 43 }
 44  int dfs( int now,  int maxf){
 45      int cnt =  0;
 46      if(now == T)  return maxf;
 47      for( int i = head[now]; i != - 1; i = edge[i].next)  if(dis[edge[i].to] == dis[now] +  1 && edge[i].f){
 48          int f = dfs(edge[i].to, min(maxf - cnt, edge[i].f));
 49         edge[i].f -= f; edge[i^ 1].f += f; cnt += f;
 50          if(!f) dis[edge[i].to] = - 1;
 51          if(cnt == maxf)  return cnt;
 52     } return cnt;
 53 }
 54  int dinic( int s,  int t){
 55      int ret =  0;
 56      while(bfs()){ ret += dfs(s, INF);}
 57      return ret;
 58 }
 59  int main(){
 60     scanf( " %d%d%d ", &X, &Y, &n);
 61     memset(head, - 1 ,  sizeof(head));
 62      for( int i =  1; i <= n; i ++){
 63         scanf( " %d ", &p[i].kk);
 64          if(p[i].kk ==  1) scanf( " %d%d%d ", &p[i].x1, &p[i].y1, &p[i].r1);
 65          else scanf( " %d%d%d%d ", &p[i].x1, &p[i].y1, &p[i].x2, &p[i].y2);
 66     }
 67      for( int i =  1; i <= n; i ++) addedge(fi, si,  1), addedge(si, fi,  0);
 68      for( int i =  1; i <= n; i ++) {
 69          if(p[i].kk ==  1 && p[i].y1 - p[i].r1 <=  0) addedge( 0, fi, INF), addedge(fi,  00);
 70          if(p[i].kk ==  2 && p[i].y1 <=  0) addedge( 0, fi, INF), addedge(fi,  00);
 71     }
 72      for( int i =  1; i <= n; i ++){
 73          if(p[i].kk ==  1 && p[i].y1 + p[i].r1 >= Y) addedge(si, T, INF), addedge(T, si,  0);
 74          if(p[i].kk ==  2 && p[i].y2 >= Y) addedge(si, T, INF), addedge(T, si,  0);
 75     }
 76      for( int i =  1; i <= n; i ++)
 77          for( int j = i+ 1; j <= n; j ++){
 78              if(p[i].kk ==  1 && p[j].kk ==  1)
 79                  if(dist(p[i].x1, p[i].y1, p[j].x1, p[j].y1) <= p[i].r1 + p[j].r1) Add(i, j);
 80              if(p[i].kk + p[j].kk ==  3){
 81                  int ii = i, jj = j;  if(p[i].kk ==  1) swap(ii, jj);
 82                  if(dist(p[ii].x1, p[ii].y1, p[jj].x1, p[jj].y1) <= p[jj].r1) {Add(i,j);  continue;}
 83                  if(dist(p[ii].x1, p[ii].y2, p[jj].x1, p[jj].y1) <= p[jj].r1) {Add(i,j);  continue;}
 84                  if(dist(p[ii].x2, p[ii].y1, p[jj].x1, p[jj].y1) <= p[jj].r1) {Add(i,j);  continue;}
 85                  if(dist(p[ii].x2, p[ii].y2, p[jj].x1, p[jj].y1) <= p[jj].r1) {Add(i,j);  continue;}
 86                  int ys = p[jj].x1 + p[jj].r1, yx = p[jj].x1 - p[jj].r1, yz = p[jj].y1 - p[jj].r1, yo = p[jj].y1 + p[jj].r1;
 87                  if(inz(ys,p[jj].y1,ii)){Add(i, j);  continue;}
 88                  if(inz(yx,p[jj].y1,ii)) {Add(i, j);  continue;}
 89                  if(inz(p[jj].x1,yz,ii)) {Add(i, j);  continue;}
 90                  if(inz(p[jj].x1,yo,ii)) {Add(i, j);  continue;}
 91             }
 92              if(p[i].kk ==  2 && p[j].kk ==  2){
 93                  if(inz(p[i].x1, p[i].y1, j)) {Add(i, j);  continue;}
 94                  if(inz(p[i].x2, p[i].y1, j)) {Add(i, j);  continue;}
 95                  if(inz(p[i].x1, p[i].y2, j)) {Add(i, j);  continue;}
 96                  if(inz(p[i].x2, p[i].y2, j)) {Add(i, j);  continue;}
 97                  if(inz(p[j].x1, p[j].y1, i)) {Add(i, j);  continue;}
 98                  if(inz(p[j].x2, p[j].y1, i)) {Add(i, j);  continue;}
 99                  if(inz(p[j].x1, p[j].y2, i)) {Add(i, j);  continue;}
100                  if(inz(p[j].x2, p[j].y2, i)) {Add(i, j);  continue;}
101             }
102         }
103  
104     cout << dinic( 0, T) << endl;
105  //   system("pause");
106      return  0;
107 }
View Code

 

 

 

1502: [NOI2005]月下柠檬树

 

题目大意:给定一棵由圆台和圆锥构成的柠檬树,月光以α的夹角平行射向地面,求阴影部分面积

 

 把这棵树投影到地上是一个很简单的问题,注意宽度没有变化,高度被压缩了就可以了。

下面的问题就变成了求一堆圆和一堆梯形的并集的大小。

因为有圆又有梯形比较不好求,于是强行上 自适应simpson。

/*

这里插播一句所有和圆有关的东西都显然是不能直接simpson积分的,,因为 (x0 + 4*xmid + x1) / 6.0 * l 这个式子只适用于 ax^3 + bx^2 + cx^1  + d 这样的式子啊!!! 带根号的式子显然是不行的啊!!!!

窝前两天在赛场上竟然试图直接用simpson求弓形面积。。。。。真是傻爆了啊。。。

*/

/*

大家都知道simpson公式是Newton–Cotes formulas的一个特殊情况,去wiki看了一下,还有这样一个叫做Boole's rule的式子:

可以处理5次以内的函数哦!

*/

/*

以下几题窝连续写了好多次最后都因为浏览器崩了没有保存下来。。。。。可能是这几道题嫌我太弱了并不愿意让我来写题解。。所以就不仔细写了。

*/

 关于自适应simpson的正确性和复杂度都不知道怎么证明。。求大神科普

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <algorithm>
 6 #define eps 0.000001
 7 using namespace std;
 8 int n;
 9 double alpha, H[505], R[505], ll = 1<<30, rr = -(1<<30);
10 struct Line{double x1, y1, x2, y2;}L[505];
11 double S(double x){
12     double ret = 0;
13     for(int i = 1; i <= n; i ++) if(H[i]-R[i] <= x && H[i]+R[i] >= x)
14         ret = max(ret, sqrt(R[i]*R[i] - (x-H[i])*(x-H[i])));
15     for(int i = 1; i < n; i ++) if(L[i].x1 <= x & L[i].x2 >= x)
16         ret = max(ret, L[i].y1 - (L[i].y1-L[i].y2) * (x-L[i].x1) / (L[i].x2-L[i].x1));
17     return ret;
18 }
19 double Simpson(double l, double r){
20     double mid = (l + r) / 2.0;
21     return (S(l) + 4*S(mid) + S(r))/6;
22 }
23 double Calc(double l, double r){
24     double mid = (l + r) / 2.0, ret = Simpson(l, r)*(r-l);
25     if(fabs(ret - Simpson(l, mid)*(mid-l) - Simpson(mid, r)*(r-mid)) <= eps) return ret;
26     return Calc(l, mid) + Calc(mid, r);
27 }
28 int main(){
29     cin >> n >> alpha;
30     alpha = 1.0 / tan(alpha); n ++;
31     for(int i = 1; i <= n; i ++) scanf("%lf", &H[i]), H[i] *= alpha, H[i] += H[i-1];
32     for(int i = 1; i < n; i ++) scanf("%lf", &R[i]), ll = min(ll, H[i]-R[i]), rr = max(rr, H[i]+R[i]); 
33     R[n] = 0.0; ll = min(ll, H[n]-R[n]); rr = max(rr, H[n] + R[n]);
34     for(int i = 1; i < n; i ++){
35         double sina = (R[i]-R[i+1])/(H[i+1]-H[i]);
36         L[i].x1 = H[i] + R[i]*sina; L[i].x2 = H[i+1] + R[i+1]*sina;
37         L[i].y1 = sqrt(R[i]*R[i] - (L[i].x1-H[i])*(L[i].x1-H[i]));
38         L[i].y2 = sqrt(R[i+1]*R[i+1] - (L[i].x2-H[i+1])*(L[i].x2-H[i+1]));
39     }
40     printf("%.2lf", 2*Calc(ll, rr));
41     return 0;
42 }
View Code

 

 

 

 

转载于:https://www.cnblogs.com/lixintong911/p/4954408.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
计算几何 算法与应用》(Computational Geometry: Algorithms and Applications) 是由Mark de Berg, Otfried Cheong, Marc van Kreveld和Mark Overmars等人合著的一本计算几何领域的经典教材。该书是关于计算几何算法和应用的权威指南,深入介绍了计算几何的基本概念、算法和应用。这本书被广泛应用于计算机科学、地理信息系统、计算机视觉和人工智能等领域。 这本书主要涵盖了计算几何的许多重要主题,包括平面和空间几何、线段、多边形、凸包、三角剖分、区域和方框树、点定位和射线距离、几何搜索问题、平面点排序、和可见性图等。它详细介绍了这些主题的算法和数据结构,并提供了大量的示例和应用场景。读者可以通过学习这些算法和数据结构,理解和解决各种实际计算几何问题。 这本书的特点之一是它提供了丰富的图形示例和可视化。读者可以通过这些示例更好地理解和应用计算几何算法。此外,该书还提供了习题和练习题,帮助读者巩固所学知识,并对各种算法进行实践。 《计算几何 算法与应用》是计算几何领域的经典教材,它详细介绍了计算几何的基本概念、算法和应用。它适用于计算机科学、地理信息系统、计算机视觉和人工智能等领域的学生、研究人员和专业人士。无论是初学者还是专家,都可以从这本书中获得有关计算几何的全面知识和实用技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值