1.  

The famous Korean internet company nhn has provided an internet-based photo service which allows The famous Korean internet company users to directly take a photo of an astronomical phenomenon in
space by controlling a high-performance telescope owned by nhn. A few days later, a meteoric shower, known as the biggest one in this century, is expected. nhn has announced a photo competition which awards the user who takes a photo containing as many meteors
as possible by using the photo service. For this competition, nhn provides the information on the trajectories of the meteors at their web page in advance. The best way to win is to compute the moment (the time) at which the telescope can catch the maximum
number of meteors.

You have n meteors, each moving in uniform linear motion; the meteor mi moves along the trajectory pi + t×vi over
time t , wheret is a non-negative real value, pi is the starting point of mi and vi is
the velocity of mi . The point pi = (xiyi) is represented by X -coordinate xi and Y -coordinate yi in
the (XY) -plane, and the velocity vi = (aibi) is a non-zero vector with two components ai and bi in
the (XY) -plane. For example, if pi = (1, 3) and vi = (-2, 5) , then the meteor mi will
be at the position (0, 5.5) at time t = 0.5 because pi + t×vi = (1, 3) + 0.5×(-2, 5) = (0, 5.5) . The telescope has a rectangular frame with the lower-left
corner (0, 0) and the upper-right corner (wh) . Refer to Figure 1. A meteor is said to be in the telescope frame if the meteor is in the interior of the frame (not on the boundary of the frame). For exam! ple,
in Figure 1, p2,p3p4 , and p5 cannot be taken by the telescope at any time because they do not pass the interior of the frame
at all. You need to compute a time at which the number of meteors in the frame of the telescope is maximized, and then output the maximum number of meteors.

Input

Your program is to read the input from standard input. The input consists of T test cases. The number of test cases T is given in the first line
of the input. Each test case starts with a line containing two integers w and h (1wh100,
000) , the width and height of the telescope frame, which are separated by single space. The second line contains an integer n , the number of input points (meteors), 1n100,
000 . Each of the next n lines contain four integers xiyiai , and bi ; (xiyi) is
the starting point pi and (aibi) is the nonzero velocity vector vi of the i -th
meteor; xi and yi are integer values between -200,000 and 200,000, and ai and bi are
integer values between -10 and 10. Note that at least one of ai and bi is not zero. These four values are separated by single spaces. We assume that all starting points pi are
distinct.

Output

Your program is to write to standard output. Print the maximum number of meteors which can be in the telescope frame at some moment.

  1. 2
  2. 4 2
  3. 2
  4. -1 1 1 -1
  5. 5 2 -1 -1
  6. 13 6
  7. 7
  8. 3 -2 1 3
  9. 6 9 -2 -1
  10. 8 0 -1 -1
  11. 7 6 10 0
  12. 11 -2 2 1
  13. -2 4 6 -1
  14. 3 2 -5 -1
  1. 1
  2. 2
 一.转化模型
  很容易就发现,流星通过镜框的时间是一段区间。
  那么问题可以等价于 找一个点,使他最多被多少个区间包含,输出区间数量最大值


 二.离散化+扫描线
  将点离散化存储,并且排序。当扫描线扫过左端点 now+1 右端点 now-1 其中出现的最大的now即为ans

 注意:
   如果时间相同的话 先右端点,后左端点。

  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <ctime>
  6. #include <algorithm>
  7. #include <iostream>
  8. #include <sstream>
  9. #include <string>
  10. #define oo 2000000;
  11. #define maxn 100001
  12. using namespace std;
  13. struct point
  14. {
  15. double x;
  16. int flag;
  17. };
  18. point P[maxn*10]; int tot=0;
  19. int w,h,n;
  20. int x,y,a,b;
  21. int getQuJian()
  22. {
  23. double t1,t2;
  24. double t3,t4;
  25. if(a!=0)
  26. t1=((double)(-x)/a),t2=(double)(w-x)/a;
  27. else
  28. {
  29. if (0<x&&x<w) { t1=0,t2=oo;}
  30. else
  31. {
  32. t1=0;t2=0;
  33. }
  34. }
  35.  
  36. if(b!=0)
  37. t3=((double)(-y)/b),t4=(double)(h-y)/b;
  38. else
  39. {
  40. if(0<y&&y<h){t3=0,t4=oo;}
  41. else t3=0,t4=0;
  42. }
  43. if(a<0) swap(t1,t2);
  44. if(b<0) swap(t3,t4);
  45. if(t1>t2) return 0;
  46. if(t3>t4) return 0;
  47. if(t1<=t3)
  48. {
  49. if(t3<=t2)
  50. {
  51. if(t2<=t4)
  52. {
  53. if(t2!=t3)
  54. {
  55. if(t3<0&&t2>0) t3=0;
  56. P[++tot].x=t3;P[tot].flag=0;
  57. P[++tot].x=t2;P[tot].flag=1;
  58. }
  59. }
  60. else
  61. {
  62. if(t3!=t4)
  63. {
  64. if(t3<0&&t4>0) t3=0;
  65. P[++tot].x=t3;P[tot].flag=0;
  66. P[++tot].x=t4;P[tot].flag=1;
  67. }
  68. }
  69. }
  70. else;
  71. }
  72. else
  73. {
  74. if(t1<=t4)
  75. {
  76. if(t4<=t2)
  77. {
  78. if(t1!=t4)
  79. {
  80. if(t1<0&&t4>0) t1=0;
  81. P[++tot].x=t1;P[tot].flag=0;
  82. P[++tot].x=t4;P[tot].flag=1;
  83. }
  84. }
  85. else
  86. {
  87. if(t1!=t2)
  88. {
  89. if(t1<0&&t2>0) t1=0;
  90. P[++tot].x=t1;P[tot].flag=0;
  91. P[++tot].x=t2;P[tot].flag=1;
  92. }
  93. }
  94. }
  95. }
  96. return 0;
  97. }
  98. int cmp(const void *i,const void *j)
  99. {
  100. point *ii=(point *)i,*jj=(point *)j;
  101. if(ii->x!=jj->x)
  102. if(ii->x>jj->x) return 1;
  103. else return -1;
  104. else return jj->flag-ii->flag;
  105. }
  106. int main()
  107. {
  108. freopen("a.in","r",stdin);
  109. freopen("a.out","w",stdout);
  110. int T,ans,now;
  111. cin>>T;
  112. while(T--)
  113. {
  114. tot=0,ans=0,now=0;
  115. cin>>w>>h;
  116. cin>>n;
  117. for(int i=1;i<=n;i++)
  118. {
  119. cin>>x>>y>>a>>b;
  120. getQuJian();
  121. }
  122. qsort(P+1,tot,sizeof(P[1]),cmp);
  123. for(int i=1;i<=tot;i++)
  124. {
  125. if(P[i].x>0)
  126. {
  127. if(P[i].flag==1) now--;
  128. else
  129. {
  130. now++;
  131. ans=max(ans,now);
  132. }
  133. }
  134. else if(P[i].x==0&&P[i].flag==0)
  135. {
  136. now++;
  137. ans=max(ans,now);
  138. }
  139. }
  140. cout<<ans<<endl;
  141. }
  142. return 0;
  143. }

刘汝佳老师的求交集写的更优美(左端点与左端点比,右端点与右端点比,并且初始区间为【0,+oo】,使得没有我那么多麻烦的判断)


  1. void update(int x, int a, int w, double& L, double& R) {
  2. if(a == 0) {
  3. if(x <= 0 || x >= w) R = L-1; //无解
  4. } else if(a > 0) {
  5. L = max(L, -(double)x/a);
  6. R = min(R, (double)(w-x)/a);
  7. } else {
  8. L = max(L, (double)(w-x)/a);
  9. R = min(R, -(double)x/a);
  10. }
  11. }

刘汝佳老师的整个题目解释:

【分析】

不难发现,流星的轨迹是没有直接意义的,有意义的只是每个流星在照相机视野内出现的时间段。换句话说,我们把本题抽象为这样一个问题:给出n个开区间(Li,Ri),你的任务是求出一个数t,使得包含它的区间数最多(为什么是开区间呢?请读者思考)。开区间(Li,Ri)是指所有满足Li<x
<Ri的实数x的集合。

把所有区间画到平行于数轴的直线上(免得相互遮挡,看不清楚),然后想象有一条竖直线从左到右进行扫描,则问题可以转化为:求扫描线在哪个位置时与最多的开区间相交,如图1-27所示。

图  1-27

不难发现,当扫描线移动到某个区间左端点的“右边一点点”时最有希望和最多的开区间相交(想一想,为什么)。为了快速得知在这些位置时扫描线与多少条线段相交,我们再一次使用前面提到的技巧:维护信息,而不是重新计算。

我们把“扫描线碰到一个左端点”和“扫描线碰到一个右端点”看成是事件(event),则扫描线移动的过程就是从左到右处理各个事件的过程。每遇到一个“左端点事件”,计数器加1;每遇到一个“右端点事件”,计数器减1。这里的计数器保存的正是我们要维护的信息:扫描线和多少个开区间相交,如图1-28所示。

图  1-28

这样,我们可以写出这样一段伪代码。

将所有事件按照从左到右排序

while(还有未处理的事件) {

选择最左边的事件E

if(E是“左端点事件”) { cnt++; if(cnt > ans) ans= cnt; } //更新计数器和答案

else cnt--;//一定是“右端点事件”

}

这段伪代码看上去挺有道理,但实际上暗藏危险:如果不同事件的端点相同,那么哪个排在前面呢?考虑这样一种情况——输入是两个没有公共元素的开区间,且左边那个区间的右端点和右边那个区间的左端点重合。在这种情况下,两种排法的结果截然不同:如果先处理左端点事件,执行结果是2;如果先处理右端点事件,执行结果是1。这才是正确答案。

这样,我们得到了一个完整的扫描算法:先按照从左到右的顺序给事件排序,对于位置相同的事件,把右端点事件排在前面,然后执行上述伪代码的循环部分。如果你对这个冲突解决方法心存疑虑,不妨把它理解成把所有区间的右端点往左移动了一个极小(但大于0)的距离。


  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. //0<x+at<w
  5. void update(int x, int a, int w, double& L, double& R) {
  6. if(a == 0) {
  7. if(x <= 0 || x >= w) R = L-1; //无解
  8. } else if(a > 0) {
  9. L = max(L, -(double)x/a);
  10. R = min(R, (double)(w-x)/a);
  11. } else {
  12. L = max(L, (double)(w-x)/a);
  13. R = min(R, -(double)x/a);
  14. }
  15. }
  16.  
  17. const int maxn = 100000 + 10;
  18.  
  19. struct Event {
  20. double x;
  21. int type;
  22. bool operator < (const Event& a) const {
  23. return x < a.x || (x == a.x && type > a.type); //先处理右端点
  24. }
  25. } events[maxn*2];
  26.  
  27. int main() {
  28. int T;
  29. scanf("%d", &T);
  30. while(T--) {
  31. int w, h, n, e = 0;
  32. scanf("%d%d%d", &w, &h, &n);
  33. for(int i = 0; i < n; i++) {
  34. int x, y, a, b;
  35. scanf("%d%d%d%d", &x, &y, &a, &b);
  36. //0<x+at<w, 0<y+bt<h, t>=0
  37. double L = 0, R = 1e9;
  38. update(x, a, w, L, R);
  39. update(y, b, h, L, R);
  40. if(R > L) {
  41. events[e++] = (Event){L, 0};
  42. events[e++] = (Event){R, 1};
  43. }
  44. }
  45. sort(events, events+e);
  46. int cnt = 0, ans = 0;
  47. for(int i = 0; i < e; i++) {
  48. if(events[i].type == 0) ans = max(ans, ++cnt);
  49. else cnt--;
  50. }
  51. printf("%d\n", ans);
  52. }
  53. return 0;
  54. }

另外,本题还可以完全避免实数运算,全部采用整数:只需要把代码中的double全部改成int,然后在update函数中把所有返回值乘以lcm(1,2,…,10)=2 520即可(想一想,为什么)。

因为2520 是他们的公倍数 除出来必定是整数

  1. void update(int x, int a, int w, int& L,int& R) {
  2. if(a == 0){
  3. if(x<= 0 || x >= w) R = L-1; //无解
  4. } else if(a> 0) {
  5. L =max(L, -x*2520/a);
  6. R =min(R, (w-x)*2520/a);
  7. } else {
  8. L =max(L, (w-x)*2520/a);
  9. R =min(R, -x*2520/a);
  10. }
  11. }

【转换模型+扫描线】【UVA1398】Meteor的更多相关文章

  1. 性能测试学习之三—— PV->TPS转换模型&TPS波动模型

    PV->TPS转换模型 由上一篇“性能测试学习之二 ——性能测试模型(PV计算模型)“ 得知 TPS = ( (80%*总PV)/(24*60*60*(T/24)))/服务器数量 转换需要注意: ...

  2. [源码解析] 深度学习流水线并行 PipeDream(3)--- 转换模型

    [源码解析] 深度学习流水线并行 PipeDream(3)--- 转换模型 目录 [源码解析] 深度学习流水线并行 PipeDream(3)--- 转换模型 0x00 摘要 0x01 前言 1.1 改 ...

  3. Uva1398 Meteor

    扫描线法. 将流星出现在相机里的时间转化成线段,离散化端点后,扫描何时出现的流星最多.注意边界的不算,所以要先减右端点再加左端点 /*By SilverN*/ #include<iostream ...

  4. 使用Blender批量导出/转换模型

    2.4版本号的Blender API和2.5以上版本号的API有非常大的不同,这里仅仅是提供了思路和2.4版本号的导出方案. 先提供一个脚本,这个是由Blender调用的.用于转换Ogre的Mesh文 ...

  5. 全参考视频质量评价方法(PSNR,SSIM)以及与MOS转换模型

    转载处:http://blog.csdn.NET/leixiaohua1020/article/details/11694369 最常用的全参考视频质量评价方法有以下2种: PSNR(峰值信噪比):用 ...

  6. 动态规划(模型转换):uvaoj 1625 Color Length

    [PDF Link]题目点这里 这道题一眼就是动态规划,然而貌似并不好做. 如果不转换模型,状态是难以处理的. 巧妙地转化:不直接求一种字母头尾距离,而是拆开放到状态中. #include <i ...

  7. [转]kaldi特征和模型空间转换

    转:http://blog.csdn.net/shmilyforyq/article/details/76807431 博主话:这篇博客是对kaldi官网中Feature and model-spac ...

  8. 3D模型预处理(格式转换:obj转换为gltf)

    在cesium中导入模型需要的是gltf或glb格式的文件,cesium官方提供了obj转gltf文件的工具,一个obj2gltf的库,地址为https://github.com/Analytical ...

  9. Pytorch | BERT模型实现,提供转换脚本【横扫NLP】

    <谷歌终于开源BERT代码:3 亿参数量,机器之心全面解读>,上周推送的这篇文章,全面解读基于TensorFlow实现的BERT代码.现在,PyTorch用户的福利来了:一个名为Huggi ...

随机推荐

  1. Microsoft Visual C++ 不支持long long

    Microsoft Visual C++ 不支持long long 在C/C++中,64为整型一直是一种没有确定规范的数据类型.现今主流的编译器中,对64为整型的支持也是标准不一,形态各异.一般来说, ...

  2. CSS减肥的工具–Firefox插件 CSS Usage

    首先,我们需要安装Firefox(猛击此处下载),或者确定你已经安装的版本已经高于3.1; 第二步,安装前端开发人员最普及的开发工具 Firebug: 第三步,安装CSS Usage 0.3.4.1: ...

  3. HTML5 本地裁剪图片并上传至服务器(转)

    很多情况下用户上传的图片都需要经过裁剪,比如头像啊什么的.但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 ...

  4. axure 8.0 动态特效库分享

    认准品牌 六脉神掌 尽量给每一个交互加上效果,尽量模拟真实的交互 无图无真相,我们先看效果图 1 这是还原Android Material Design风格的一个底部菜单效果 2 这个是模拟欢迎页面 ...

  5. .net 基础之截取字符串

    在实际开发中有时难免会遇到需要获取某个字符串中的某些字符串,这里我们可以用到字符串截取的办法. 截取字符串的方法很容易(暂不包含中文字符串),只要稍微有点.net基础的人看了都能看懂. /// < ...

  6. C#中Dispose、析构函数、close的区别

    一.Close与Dispose这两种方法的区别 调用完了对象的Close方法后,此对象有可能被重新进行使用:而Dispose方法来说,此对象所占有的资源需要被标记为无用了,也就是此对象要被销毁,不能再 ...

  7. jquery file upload 后台收到的文件名中文乱码, filename中文乱码

    在jQuery File Upload.js文件里,在以下这个js中有个成员叫做 _initXHRData, 是一个function, 在这个function的最后部分有一个if-else分支,如下:

  8. 【转载】solr教程,值得刚接触搜索开发人员一看

    转载:http://blog.csdn.net/awj3584/article/details/16963525 Solr调研总结 开发类型 全文检索相关开发 Solr版本 4.2 文件内容 本文介绍 ...

  9. 清除浮动 .clearfix

    子元素的浮动 清除子元素的浮动 .clearfix{zoom:1}/*IE 6-8*/.clearfix:after{content:'\20';display:block;height:0;clea ...

  10. ASP.NET MVC 4.0 学习3-Model

    Model負責獲取數據庫中的資料,並對數據庫中的數據進行處理. MVC中有關 數據庫 的任務都由Model來完成,Model中對數據資料進行定義,Controller和View中都會參考到Model, ...