POJ 2280 Amphiphilic Carbon Molecules 极角排序 + 扫描线
从TLE的暴力枚举 到 13313MS的扫描线 再到 1297MS的简化后的扫描线,简直感觉要爽翻啦。然后满怀欣喜的去HDU交了一下,直接又回到了TLE.....泪流满面
虽说HDU的时限是2000MS 可是数据也忒强了点吧,真心给HDU跪了。
题意:给定平面上的N个点,属性分别标记为0和1,然后找一条直线,直线上的点全部溶解,一侧的1溶解,另一侧的0溶解。求出最多能溶解的点的个数。
思路:最直接的思路就是O(N^3)的暴力枚举,Discuss里面貌似有大牛过了,肯能是我太过暴力了吧,果断Tle了,然后换成了枚举单个点,然后极角排序+扫描线,
跑了13313MS。然后优化了一下跑了1297MS。下面说一下扫描线的思路。
首先,确定射线v1,v2与X轴正方向的角度,一个为0,一个为PI,然后同时旋转,每碰到一个点就计算一次v1,v2之间的及在两条射线上的点。
直到v1与X轴的方向 >= PI ,当前这一次计算结束,继续枚举下一个点。
这就是13313MS那份代码的思路,显然扫描线是没错的,但是有一些点被重复计算了,其实我们只需要计算α角区域内的点的个数,通过它来维
护v1,v2区域内的点的个数,优化后用时就减少到了1297MS,但是在HDU依然过不了......
POJ AC_Code 1297MS
- #include <iostream>
- #include <cstring>
- #include <cstdlib>
- #include <cstdio>
- #include <queue>
- #include <cmath>
- #include <algorithm>
- #include <string>
- #define LL long long
- #define EPS (1e-8)
- using namespace std;
- const double PI = acos(-1.0);
- struct P
- {
- double a;
- int x,y,mark;
- } pa[1010],p[1010];
- double Cal_Angle(P p1,P p2)
- {
- if(p1.x == p2.x && p1.y == p2.y)
- return -100.0;
- P v;
- v.x = p2.x - p1.x;
- v.y = p2.y - p1.y;
- if(p1.y <= p2.y)
- return acos(v.x/sqrt(v.x*v.x + v.y*v.y));
- return 2.0*PI - acos(v.x/sqrt(v.x*v.x + v.y*v.y));
- }
- void Cal_Angle(P p,P *pa,int n)
- {
- for(int i = 0; i < n; ++i)
- {
- pa[i].a = Cal_Angle(p,pa[i]);
- }
- }
- bool cmp_angle(P p1,P p2)
- {
- return p1.a < p2.a;
- }
- int main()
- {
- int n,i,j,k,l,d;
- int Max,tl,tr,b,w,s1,s0,s2,s3;
- double xm,pil,pir;
- P vec;
- while(scanf("%d",&n) && n)
- {
- b = 0;
- w = 0;
- for(i = 0; i < n; ++i)
- {
- scanf("%d %d %d",&p[i].x,&p[i].y,&p[i].mark);
- pa[i] = p[i];
- if(pa[i].mark)
- b++;
- else
- w++;
- }
- Max = -1;
- for(i = 0; i < n; ++i)
- {
- Cal_Angle(p[i],pa,n);
- sort(pa,pa+n,cmp_angle);
- pir = pa[1].a;
- pil = pir + PI;
- s1 = s0 = s2 = s3 = 0;
- for(j = 1; j < n && pa[j].a < pil; ++j)
- {
- if(pa[j].a == pir)
- {
- if(pa[j].mark)
- s3++;
- else
- s2++;
- }
- else
- {
- if(pa[j].mark)
- s1++;
- else
- s0++;
- }
- }
- for(d = j; d < n && pa[d].a == pil; ++d)
- {
- if(pa[d].mark)
- s3++;
- else
- s2++;
- }
- if(pa[0].mark)
- s3++;
- else
- s2++;
- tr = s0 + (b-s1)+s2;
- tl = s1 + (w-s0)+s3;
- if(tr > Max || tl > Max)
- Max = tr > tl ? tr : tl;
- k = 1;
- while(pir < PI && j < n)
- {
- for(; k < n && pir == pa[k].a; ++k)
- {
- if(pa[k].mark)
- --s3;
- else
- --s2;
- }
- pir = pa[k].a;
- if(pir > PI)
- break;
- for(l = k; l < n && pir == pa[l].a; ++l)
- {
- if(pa[l].mark)
- {
- ++s3;
- --s1;
- }
- else
- {
- ++s2;
- --s0;
- }
- }
- for(; j < n && pa[j].a == pil; ++j)
- {
- if(pa[j].mark)
- {
- --s3;
- ++s1;
- }
- else
- {
- --s2;
- ++s0;
- }
- }
- pil = pir+PI;
- for(; j < n && pa[j].a < pil; ++j)
- {
- if(pa[j].mark)
- {
- ++s1;
- }
- else
- {
- ++s0;
- }
- }
- for(d = j; d < n && pa[d].a == pil ; ++d)
- {
- if(pa[d].mark)
- ++s3;
- else
- ++s2;
- }
- tr = s0 + (b-s1)+s2;
- tl = s1 + (w-s0)+s3;
- if(tr > Max || tl > Max)
- {
- Max = tr > tl ? tr : tl;
- }
- }
- }
- printf("%d\n",Max);
- }
- return 0 ;
- }
POJ AC_Code 13313MS
- #include <iostream>
- #include <cstring>
- #include <cstdlib>
- #include <cstdio>
- #include <queue>
- #include <cmath>
- #include <algorithm>
- #include <string>
- #define LL long long
- #define EPS (1e-8)
- using namespace std;
- const double PI = acos(-1);
- struct P
- {
- double x,y,a;
- int mark;
- }pa[1010],p[1010];
- double Cal_Angle(P p1,P p2)
- {
- if(p1.x == p2.x && p1.y == p2.y)
- return -100.0;
- P v;
- v.x = p2.x - p1.x;
- v.y = p2.y - p1.y;
- if(p1.y <= p2.y)
- return acos(v.x/sqrt(v.x*v.x + v.y*v.y));
- return 2.0*PI - acos(v.x/sqrt(v.x*v.x + v.y*v.y));
- }
- void Cal_Angle(P p,P *pa,int n)
- {
- for(int i = 0;i < n; ++i)
- {
- pa[i].a = Cal_Angle(p,pa[i]);
- }
- }
- bool cmp_angle(P p1,P p2)
- {
- return p1.a < p2.a;
- }
- int main()
- {
- int n,i,j,k;
- int tm1,tm0,tm2,tm3,Max,t1,t2,b,w;
- double xm,pil,pir;
- P vec;
- while(scanf("%d",&n) && n)
- {
- b = 0;
- w = 0;
- for(i = 0;i < n; ++i)
- {
- scanf("%lf %lf %d",&p[i].x,&p[i].y,&p[i].mark);
- pa[i] = p[i];
- if(pa[i].mark)
- b++;
- else
- w++;
- }
- Max = -1;
- for(i = 0;i < n; ++i)
- {
- Cal_Angle(p[i],pa,n);
- sort(pa,pa+n,cmp_angle);
- pir = pa[0].a;
- j = 1;
- while(pir <= PI && j < n)
- {
- for(;j < n && pa[j].a == pir; ++j)
- ;
- pir = pa[j].a;
- tm3 = 0;
- tm2 = 0;
- tm1 = 0;
- tm0 = 0;
- for(pil = pir+PI,k = j;pa[k].a < pil && k < n; ++k)
- {
- if(pa[j].a == pa[k].a)
- {
- if(pa[k].mark == 1)
- {
- tm3 ++;
- }
- else
- {
- tm2 ++;
- }
- }
- else if(pa[k].mark == 0)
- {
- tm0++;
- }
- else
- {
- tm1++;
- }
- }
- if(pa[0].mark)
- tm3++;
- else
- tm2++;
- t1 = tm1+tm2+tm3 + (w-tm0-tm2);
- t2 = tm0+tm2+tm3 + (b-tm1-tm3);
- if(Max < t1 || Max < t2)
- {
- Max = t1 > t2 ? t1 : t2;
- }
- }
- }
- printf("%d\n",Max);
- }
- return 0 ;
- }
POJ 2280 Amphiphilic Carbon Molecules 极角排序 + 扫描线的更多相关文章
- poj2280Amphiphilic Carbon Molecules(极角排序)
链接 卡了几天的破题,对于hdu的那份数据,这就一神题.. 借助极角排序,枚举以每一个点进行极角排序,然后构造两条扫描线,一个上面一个下面,两条同时走,把上线和下线的点以及上线左边的点分别统计出来,如 ...
- UVA - 1606 Amphiphilic Carbon Molecules 极角扫描法
题目:点击查看题目 思路:这道题的解决思路是极角扫描法.极角扫描法的思想主要是先选择一个点作为基准点,然后求出各点对于该点的相对坐标,同时求出该坐标系下的极角,按照极角对点进行排序.然后选取点与基准点 ...
- 【极角排序、扫描线】UVa 1606 - Amphiphilic Carbon Molecules(两亲性分子)
Shanghai Hypercomputers, the world's largest computer chip manufacturer, has invented a new class of ...
- uva 1606 amphiphilic carbon molecules【把缩写写出来,有惊喜】(滑动窗口)——yhx
Shanghai Hypercomputers, the world's largest computer chip manufacturer, has invented a new classof ...
- UVa 1606 (极角排序) Amphiphilic Carbon Molecules
如果,没有紫书上的翻译的话,我觉得我可能读不懂这道题.=_=|| 题意: 平面上有n个点,不是白点就是黑点.现在要放一条直线,使得直线一侧的白点与另一侧的黑点加起来数目最多.直线上的点可以看作位于直线 ...
- UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)
任意线可以贪心移动到两点上.直接枚举O(n^3),会TLE. 所以采取扫描法,选基准点,然后根据极角或者两两做叉积比较进行排排序,然后扫一遍就好了.旋转的时候在O(1)时间推出下一种情况,总复杂度为O ...
- poj 1696 Space Ant (极角排序)
链接:http://poj.org/problem?id=1696 Space Ant Time Limit: 1000MS Memory Limit: 10000K Total Submissi ...
- POJ 1696 Space Ant 【极角排序】
题意:平面上有n个点,一只蚂蚁从最左下角的点出发,只能往逆时针方向走,走过的路线不能交叉,问最多能经过多少个点. 思路:每次都尽量往最外边走,每选取一个点后对剩余的点进行极角排序.(n个点必定能走完, ...
- POJ 1696 Space Ant(极角排序)
Space Ant Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2489 Accepted: 1567 Descrip ...
随机推荐
- win10 下 配置php环境变量
注意,只需要配置到目录即可:
- iOS 七牛多张图片上传
-(void)uploadImages:(NSArray *)images atIndex:(NSInteger)index token:(NSString *)token uploadManager ...
- U盘量产大致研究思路
这几天搞了一波U盘量产,很多年前玩的基本都是些皮毛,比如U盘分区,U盘启动,以及台电U盘的光驱启动等等,这些现在看起来其实都不入眼,只是简单的将U盘分个区,并且没玩到主控上面去. 下面是一些自己的理解 ...
- MSDN WinUSB Example
The WinUSB user-mode library uses device interface classes to communicate with the kernel-mode USB s ...
- PHP 依赖注入(DI) 和 控制反转(IoC)
要想理解 PHP 依赖注入 和 控制反转 两个概念,就必须搞清楚如下的两个问题: DI —— Dependency Injection 依赖注入 IoC —— Inversion of Control ...
- cocos2d-x学习资源汇总
http://blog.csdn.net/akof1314 http://blog.csdn.net/bill_man/ http://blog.csdn.net/fylz1125/ MoonWa ...
- Delph 两个对立程序使用消息进行控制通信
在实际应用中,总是会遇到两个独立的程序进行通信,其实通信的方式有好几种,比如进程间通信,消息通信. 项目中用到了此功能, 此功能用于锁屏程序, 下面把实现的流程和大家分享一下. 1. 在锁屏程序中,自 ...
- 使用SQL Database Migration Wizard把SQL Server 2008迁移到Windows Azure SQL Database
本篇体验使用SQL Database Migration Wizard(SQLAzureMW)将SQL Server 2008数据库迁移到 Azure SQL Database.当然,SQLAzure ...
- 统计代码执行时间,使用Stopwatch和UserProcessorTime的区别
当我们需要统计一段代码的执行时间,首先想到的可能是Stopwatch类.在这里,先暂不使用Stopwatch,自定义一个统计代码执行时间的类,大致需要考虑到: 1.确保统计的是当前进程.当前线程中代码 ...
- C#编程(二十四)----------修饰符
修饰符 修饰符即应用于类型或成员的关键字.修饰符可以指定方法的可见性,如public或private,还可以指定一项的本质,如刚发的vritual或abstract. 可见性的修饰符 修饰符 应用于 ...