Separating Pebbles

题目链接:

http://acm.hust.edu.cn/vjudge/contest/127401#problem/H

Description


http://7xjob4.com1.z0.glb.clouddn.com/1e1638de1146450534631815cbf822c6

Input


The first line of the input contains an integer K (K ≤ 20) indicating the number of test cases. The first
line of each test case consists of an integer N (N ≤ 250) indicating the number of pebbles. The next
N lines each contains a triplet (x, y, c), where x and y represent the x and y coordinates (all integers,
0 ≤ x, y ≤ 150) of a pebble point, and c represents the type of pebble: ‘o’ denoted by ‘0’ and ‘+’
denoted by ‘1’.

Output


For each test case, output ‘1’ if Dr. Y can separate the pebbles with a single straight line; if not, output
‘0’.

Sample Input


2
5
1 2 0
2 1 0
4 3 1
5 4 1
6 3 1
4
1 2 0
2 1 0
1 1 1
2 2 1

Sample Output


1
0


##题意:

给出平面上的两类点,判断是否能画一条直线将两类点完全分割开来.


##题解:

枚举任意两点组成的直线, 除了在直线上的点以外,若其余点满足分居两侧的要求,那么我只要稍微旋转一下这条直线就能满足要求.
对直线上点的特殊考虑:当直线上有若干点时,如果出现两个'o'点中间夹一个'x'的情况是无法旋转的.
所以能旋转的条件是直线上不会出现两种类型的点间隔分布.
对重点的特殊考虑:如果有重点的话,特判可能会比较多,所以干脆一开始对所有点去重. 若有两个不同类型的点重叠,那么一定不能划分.
(坑爹的是,题目的数据好像并没有重复点,在uDebug上跑类型不同的重点居然输出1).
不知不觉就打了5000B的代码,稍有点繁琐...


##代码:
``` cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define double long long
#define eps 1e-8
#define maxn 300
#define mod 100000007
#define inf 0x3f3f3f3f
#define mid(a,b) ((a+b)>>1)
#define IN freopen("in.txt","r",stdin);
using namespace std;

struct Point{

double x,y;

int tp;

Point(){}

Point(double tx,double ty) {x=tx;y=ty;}

bool operator<(const Point& b)const

{

if(x==b.x) return y<b.y;

return x<b.x;

}

}tmp[maxn];

vector p;

struct Line{

Point a,b;

};

int sign(double x)

{

if(!x) return 0;

return x<0? -1:1;

}

double xmul(Point p0,Point p1,Point p2)

{return (p1.x-p0.x)(p2.y-p0.y)-(p2.x-p0.x)(p1.y-p0.y);}

bool is_inline(Point a, Point b, Point c) {

return xmul(a,b,c) == 0;

}

/判两点在线段异侧,点在线段上返回0/

int opposite_side(Point p1,Point p2,Line l)

{

return sign(xmul(p1,l.a,l.b)*xmul(p2,l.a,l.b))<0;

}

int same_side(Point p1,Point p2,Line l)

{

return sign(xmul(p1,l.a,l.b)*xmul(p2,l.a,l.b))>0;

}

/判断两点是否重合/

int equal_point(Point p1,Point p2)

{

return (sign(p1.x-p2.x)0)&&(sign(p1.y-p2.y)0);

}

int vis[200][200];

int main(int argc, char const *argv[])

{

//IN;

  1. int t; cin >> t;
  2. while(t--)
  3. {
  4. int n; scanf("%d", &n);
  5. memset(vis, -1, sizeof(vis));
  6. p.clear(); p.push_back(Point(0,0));
  7. bool flag = 1;
  8. int m = 0;
  9. for(int i=1; i<=n; i++) {
  10. scanf("%lld %lld %d", &tmp[i].x, &tmp[i].y, &tmp[i].tp);
  11. }
  12. //sort(p+1, p+1+n);
  13. /*去重*/
  14. for(int i=1; i<=n; i++) {
  15. if(vis[tmp[i].x][tmp[i].y] == -1) {
  16. vis[tmp[i].x][tmp[i].y] = tmp[i].tp;
  17. p.push_back(tmp[i]);
  18. m++;
  19. } else {
  20. if(vis[tmp[i].x][tmp[i].y] != tmp[i].tp) {
  21. flag = 0;
  22. break;
  23. }
  24. }
  25. }
  26. if(!flag) { /*如果有两类点重叠,无法划分*/
  27. printf("0\n");
  28. continue;
  29. }
  30. vector<int> in; /*在直线上的点*/
  31. vector<int> a; /*A类点'o'*/
  32. vector<int> b; /*B类点'x'*/
  33. for(int i=1; i<=m; i++) {
  34. for(int j=i+1; j<=m; j++) {
  35. flag = 1;
  36. Line l; l.a = p[i]; l.b = p[j];
  37. a.clear(); b.clear(); in.clear();
  38. for(int k=1; k<=m; k++) {
  39. if(is_inline(p[i], p[j], p[k])) { /*在直线上*/
  40. in.push_back(k);
  41. continue;
  42. }
  43. if(p[k].tp == 0) {
  44. if(a.empty()) {
  45. a.push_back(k);
  46. if(!b.empty()) {
  47. /*因为只能维护是否在同一边而不能具体到是左边还是右边,所以要判断集合中的第一个点是否违背条件,样例2可以说明这一点*/
  48. if(same_side(p[k],p[b[0]],l)) {
  49. flag = 0;
  50. break;
  51. }
  52. }
  53. } else {
  54. if(opposite_side(p[a[0]],p[k],l)) {
  55. flag = 0;
  56. break;
  57. }
  58. else a.push_back(k);
  59. }
  60. continue;
  61. }
  62. if(p[k].tp == 1) {
  63. if(b.empty()) {
  64. b.push_back(k);
  65. if(!a.empty()) {
  66. if(same_side(p[k],p[a[0]],l)) {
  67. flag = 0;
  68. break;
  69. }
  70. }
  71. } else {
  72. if(opposite_side(p[b[0]],p[k],l)) {
  73. flag = 0;
  74. break;
  75. }
  76. else b.push_back(k);
  77. }
  78. continue;
  79. }
  80. }
  81. if(!flag) continue;
  82. /*对直线上的点判断是否有"间隔出现"的情况*/
  83. sort(in.begin(), in.end());
  84. int sz = in.size();
  85. bool change = 0;
  86. int last = p[in[0]].tp;
  87. for(int k=1; k<sz; k++) {
  88. if(p[in[k]].tp != last) {
  89. if(!change) {
  90. last = p[in[k]].tp;
  91. change = 1;
  92. }
  93. else {
  94. flag = 0;
  95. break;
  96. }
  97. }
  98. }
  99. if(flag) {
  100. //printf("%d %d\n", i,j);
  101. goto las;
  102. }
  103. }
  104. }
  105. las:
  106. if(flag) printf("1\n");
  107. else printf("0\n");
  108. }
  109. return 0;

}

UVALive 7461 Separating Pebbles (计算几何)的更多相关文章

  1. UVaLive 7461 Separating Pebbles (暴力)

    题意:给出平面上的两类点,判断是否能画一条直线将两类点完全分割开来. 析:用暴力去枚举任意两点当作直线即可. 代码如下: #pragma comment(linker, "/STACK:10 ...

  2. UVALive7461 - Separating Pebbles 判断两个凸包相交

    //UVALive7461 - Separating Pebbles 判断两个凸包相交 #include <bits/stdc++.h> using namespace std; #def ...

  3. UVALive 4428 Solar Eclipse --计算几何,圆相交

    题意:平面上有一些半径为R的圆,现在要在满足不与现有圆相交的条件下放入一个圆,求这个圆能放的位置的圆心到原点的最短距离. 解法:我们将半径扩大一倍,R = 2*R,那么在每个圆上或圆外的位置都可以放圆 ...

  4. UVaLive 6693 Flow Game (计算几何,线段相交)

    题意:给个棋盘,你可以在棋盘的边缘处放2个蓝色棋子2个黄色棋子,问连接2组同色棋子的最小代价,如果线路交叉,输-1. 析:交叉么,可以把它们看成是两条线段,然后如果相交就是不行的,但是有几种特殊情况, ...

  5. UVALive 7749 Convex Contour (计算几何)

    题意:给定上正方形,圆,三角形,让你求出包围它的最短的路径. 析:首先,如果是这种情况  三角形 三角形 三角形 正方形(圆) 三角形 三角形 三角形 ..这一种就是直接从左边直接连到正方形(圆),也 ...

  6. UVALIVE 5893 计算几何+搜索

    题意:很复杂的题意,我描述不清楚. 题目链接:http://acm.bnu.edu.cn/bnuoj/contest_show.php?cid=3033#problem/33526 大致是,给定一个起 ...

  7. UVALive 4426 Blast the Enemy! 计算几何求重心

    D - Blast the Enemy! Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Subm ...

  8. UVALive 4818 - Largest Empty Circle on a Segment (计算几何)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  9. 【计算几何】【辛普森积分法】UVALive - 7076 - Highway

    春节前后想了好久才在队友的讲解下想明白…… 太难讲了,我就不讲了,大概就是考虑直着走到高速上还是斜着走到高速上,然后平移直线和大圆相切,把生成的最大的“桥”和大圆并一下就行了. #include< ...

随机推荐

  1. 自定义View(3)关于canas.drawText

    本文以Canvas类的下面这个函数为基础,它用来在画布上绘制文本. public void drawText(String text, float x, float y, Paint paint) 效 ...

  2. NDK(20)JNI的5大性能缺陷及优化技巧

    转自 : http://www.ibm.com/developerworks/cn/java/j-jni/index.html JNI 编程缺陷可以分为两类: 性能:代码能执行所设计的功能,但运行缓慢 ...

  3. Android开发之onActivityResult()中的resultCode为0,intent为null的解决办法

    BUG:昨天在使用activity之间传值的时候,遇到了一个bug,该bug为:Activity A启动Activity B,然后在Activity B中取到一个值,并通过back键返回到Activi ...

  4. windows 下 apache设置

    apache,apache配置,配置端口 mac下apache配置 添加虚拟主机: Alias /selftest/ "D:/self-test/" <Directory & ...

  5. android中getSystemService详解

        android的后台运行在很多service,它们在系统启动时被SystemServer开启,支持系统的正常工作,比如MountService监 听是否有SD卡安装及移除,ClipboardS ...

  6. codeforces 340C Tourist Problem(简单数学题)

    题意:固定起点是0,给出一个序列表示n个点,所有点都在一条直线上,其中每个元素代表了从起点到这个点所走的距离.已知路过某个点不算到达这个点,则从起点出发,到达所有点的方案有许多种.求所有方案走的总路程 ...

  7. 学习:java设计模式—工厂模式

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类: 1)简单工厂模式(Simple Facto ...

  8. NPAIRS框架的理解

    <The NPAIRS Computational Statistics Framework for Data Analysis in Neuroimaging> Strother. pe ...

  9. poj 3181 Dollar Dayz

    题意:给定一个数p,要求用K种币值分别为1,2,3...K的硬币组成p,问方案数,1,2,2和2,2,1算一种方案即与顺序无关,n <= 1000,k <= 100// 用完全背包做了 这 ...

  10. 一天一个Java基础——序列化

    1.概念 Java的“对象序列化”能将一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象的时候,能把这些byte数据恢复出来,并据此重新构建那个对象. 对象序列化能实 ...