链接:https://www.codechef.com/FEB18/problems/POINPOLY

Points Inside A Polygon Problem Code: POINPOLY

You have to find any ⌊N/10⌋ distinct points with integer coordinates that lie strictly insidethe polygon, or determine that such a set of points doesn't exist.

Note: ⌊⌋ denotes the floor function, typically used in integer division.

Input

  • The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
  • The first line of each test case contains a single integer N denoting the number of vertices of the polygon.
  • The following N lines describe the vertices of the polygon in anticlockwise order. Each of these lines contains two space-separated integers x and y denoting the coordinates of one vertex.

Output

For each test case, if a valid set of points doesn't exist, print a single line containing the integer -1. Otherwise, print ⌊N/10⌋ lines. Each of these lines should contain two space-separated integers denoting the coordinates of one point.

The coordinates of all points should be integers with absolute value not exceeding 109. If there are multiple solutions, you may print any one.

Constraints

  • 1 ≤ T ≤ 105
  • 10 ≤ N ≤ 105
  • sum of N over all test cases ≤ 5 · 105
  • |x|, |y| ≤ 109
  • no three vertices of the polygon will be collinear

Subtasks

Subtask #1 (30 points): 1 ≤ T ≤ 100, 10 ≤ N ≤ 100

Subtask #2 (70 points): original constraints

Example

  1. Input
  2.  
  3. 1
  4. 11
  5. 0 0
  6. 1 1
  7. 2 3
  8. 2 5
  9. 0 10
  10. -2 10
  11. -5 9
  12. -8 7
  13. -8 4
  14. -6 1
  15. -2 0
  16.  
  17. Output
  18.  
  19. 0 1
    ////////////////////////////////////////////////////////////
    看到这道题是一脸懵逼的,后来想着在每个端点附近是有四个点,至少有一个点在凸包内,最多每三个点共享一个凸包内相邻点,于是肯定可以做
    那么对于一个点,怎么判断是否在凸包内呢,我是把每个端点求出跟左右两点的直线方程式(o1求)然后先对于每一个端点,对于凸包的端点,判断是在每一条线的那一侧(根据方程式用正负值来表示)
    (但是不可能n²来求得对每个点来说,凸包端点是在线的哪一侧,所以我去了最上下左右四个点,用于判断,只要四个点是不同的,肯定至少有一个点跟判定点不共线,就可以求得是在哪一侧,后来发现出bug
    就是当最上下左右四个点指向的是两个点的时候,代码是有bug的,错误的例子就是左下右上处在最上下左右,这时候需要特判一下,如果出现了,将相同的值换成另外一个其他点就行了)
    然后对于某个端点相邻的点,求出他在两条线的哪一侧,如果跟凸包端点都相同,那就是在凸包内了,后来想着,几十个点围成一个宽为1的正方形不就gg了,所以还加了对于上下左右四个点是否也符合条件
    (后来问了zk的做法之后,发现,原来凸包是没有三点共线的吗,,,emmm我好菜)(前面会出现那个地方会出bug也是因为加了上下左右点的判定,但是这四个点集中在两个点的话,如果两点相邻,那么他们的方向值就是 0 0,这样
    任何点都会被判定成不符合)
    然后贴个自己的代码
    ///////////////////////////////////////////////////////////////////////////
  1. #include <bits/stdc++.h>
  2. #define mst(a,b) memset((a),(b), sizeof a)
  3. #define lowbit(a) ((a)&(-a))
  4. #define IOS ios::sync_with_stdio(0);cin.tie(0);
  5. using namespace std;
  6. typedef long long ll;
  7. const int mod=1e9+;
  8. const int maxn=1e5+;
  9. int n;
  10. struct point{int x,y;};
  11. struct line{ll a,b,c;};
  12. point po[maxn];
  13. line li[maxn][];
  14. int cc[maxn][];
  15. int dx[]={,,-,},dy[]={,-,,};
  16. vector<pair<int,int> >ans;
  17. int up=1e5+,down=1e5+,le=1e5+,ri=1e5+;
  18. void gtline(int i,int j,line& k){
  19. k.a=po[i].y-po[j].y;
  20. k.b=po[j].x-po[i].x;
  21. k.c=(ll)po[i].x*po[j].y-(ll)po[j].x*po[i].y;
  22. }
  23.  
  24. int dir(line&k,int x,int y){
  25. ll g=k.a*x+k.b*y+k.c;
  26. if(g==)return ;
  27. if(g<)return -;
  28. return ;
  29. }
  30. bool gg(int p,int x,int y){
  31. if(dir(li[p][],x,y)!=cc[p][])return true;
  32. if(dir(li[p][],x,y)!=cc[p][])return true;
  33. return false;
  34. }
  35. bool ok(int p,int x,int y){
  36. if(gg(p,x,y))return false;
  37. if(gg(le,x,y))return false;
  38. if(gg(ri,x,y))return false;
  39. if(gg(up,x,y))return false;
  40. if(gg(down,x,y))return false;
  41. return true;
  42. }
  43. void co(){
  44. int ne=n/;
  45. set<pair<int,int> >use;
  46. vector<int>kk;
  47. if(ans.size()<ne){printf("-1\n");return;}
  48. for(int i=;i<ans.size();++i){
  49. if(!use.count(ans[i])){
  50. use.insert(ans[i]);
  51. kk.push_back(i);
  52. --ne;
  53. if(!ne)break;
  54. }
  55. }
  56. if(ne){printf("-1\n");return;}
  57. for(int i=;i<kk.size();++i){
  58. printf("%d %d\n",ans[kk[i]].first,ans[kk[i]].second);
  59. }
  60.  
  61. }
  62. void check(){
  63. if(up==ri||up==le){
  64. int tmp=1e5+;
  65. for(int i=;i<n;++i)if(i!=ri&&i!=le){
  66. if(po[i].y>po[tmp].y)tmp=i;
  67. }
  68. up=tmp;
  69. }
  70. if(down==ri||down==le){
  71. int tmp=1e5+;
  72. for(int i=;i<n;++i)if(i!=ri&&i!=le){
  73. if(po[i].y<po[tmp].y)tmp=i;
  74. }
  75. down=tmp;
  76. }
  77. }
  78. int main(){
  79. #ifdef local
  80. freopen("in.txt","r",stdin);
  81. //freopen("out.txt","w",stdout);
  82. #endif
  83. int t;scanf("%d",&t);
  84. po[up].y=-1e9-;po[down].y=1e9+;po[le].x=1e9+;po[ri].x=-1e9-;
  85. while(t--){
  86. up=1e5+,down=1e5+,le=1e5+,ri=1e5+;
  87. scanf("%d",&n);
  88. for(int i=;i<n;++i){
  89. scanf("%d%d",&po[i].x,&po[i].y);
  90. if(po[i].x<po[le].x)le=i;
  91. if(po[i].x>po[ri].x)ri=i;
  92. if(po[i].y>po[up].y)up=i;
  93. if(po[i].y<po[down].y)down=i;
  94. }
  95. check();
  96. for(int i=;i<n;++i){
  97. for(int j=;j<;++j){
  98. int ad=(j==?-:);
  99. gtline(i,(i+ad+n)%n,li[i][j]);cc[i][j]=;
  100. cc[i][j]=dir(li[i][j],po[le].x,po[le].y);
  101. if(!cc[i][j])
  102. cc[i][j]=dir(li[i][j],po[ri].x,po[ri].y);
  103. if(!cc[i][j])
  104. cc[i][j]=dir(li[i][j],po[up].x,po[up].y);
  105. if(!cc[i][j])
  106. cc[i][j]=dir(li[i][j],po[down].x,po[down].y);
  107. }
  108. }
  109. ans.clear();
  110. for(int i=;i<n;++i){
  111. for(int j=;j<;++j){
  112. if(ok(i,po[i].x+dx[j],po[i].y+dy[j])){
  113. ans.push_back(make_pair(po[i].x+dx[j],po[i].y+dy[j]));
  114. break;
  115. }
  116. }
  117. }
  118. co();
  119. }
  120. return ;
  121. }

zk 的做法是根据端点坐标的奇偶性分成四类,这样数量最多的一类至少有n/4个点(鸽笼原理),然后因为三点不共线,由于凸包每两个端点的中点一定在凸包内,或是在端点连线上(两点相邻)

由于三点不共线,所以,做多那个类以至少可以产出n/4-2个端点,这个极限情况只有当n==10可能出现,实际能够产出点应该是(n/4)²级别的(这是我猜的)

然后放一下根据zk的解法写的代码(瞬间短了很多)

//////////////////////////////////////////////////////////////

  1. #include <bits/stdc++.h>
  2. #define mst(a,b) memset((a),(b), sizeof a)
  3. #define lowbit(a) ((a)&(-a))
  4. #define IOS ios::sync_with_stdio(0);cin.tie(0);
  5. using namespace std;
  6. typedef long long ll;
  7. const int mod=1e9+;
  8. const int maxn=1e5+;
  9. int x[maxn],y[maxn];
  10. vector<int>has[][];
  11. vector<pair<int,int> >ans;
  12. set<pair<int,int> >uu;
  13. int main(){
  14. #ifdef local
  15. freopen("in.txt","r",stdin);
  16. //freopen("out.txt","w",stdout);
  17. #endif
  18. int t;scanf("%d",&t);
  19. while(t--){
  20. int n;scanf("%d",&n);
  21. for(int i=;i<;++i)for(int j=;j<;++j)has[i][j].clear();
  22. for(int i=;i<n;++i){
  23. scanf("%d%d",&x[i],&y[i]);
  24. has[abs(x[i])%][abs(y[i])%].push_back(i);
  25. }
  26. int a=,b=;
  27. for(int i=;i<;++i)for(int j=;j<;++j)
  28. if(has[i][j].size()>has[a][b].size())a=i,b=j;
  29. int ne=n/; ans.clear(); uu.clear();
  30. for(int i=;i<has[a][b].size();++i){
  31. for(int j=i+;j<has[a][b].size();++j){
  32. int l=has[a][b][i],r=has[a][b][j];
  33. if(l+==r||l==&&r==n-)continue;
  34. int mx=(x[l]+x[r])>>,my=(y[l]+y[r])>>;
  35. if(!uu.count(make_pair(mx,my))){
  36. ans.push_back(make_pair(mx,my));
  37. uu.insert(make_pair(mx,my));
  38. --ne;
  39. }
  40. if(!ne)break;
  41. }
  42. if(!ne)break;
  43. }
  44. for(int i=;i<ans.size();++i)printf("%d %d\n",ans[i].first,ans[i].second);
  45. }
  46. return ;
  47. }

安慰一下自己emm我的代码比zk的多适用与正方性那种样例(非凸包)orz

CodeChef---- February Challenge 2018----Points Inside A Polygon的更多相关文章

  1. CodeChef February Challenge 2018 Points Inside A Polygon (鸽笼原理)

    题目链接  Points Inside A Polygon 题意  给定一个$n$个点的凸多边形,求出$[ \frac{n}{10}]\ $个凸多边形内的整点. 把$n$个点分成$4$类: 横坐标奇, ...

  2. codechef February Challenge 2018 简要题解

    比赛链接:https://www.codechef.com/FEB18,题面和提交记录是公开的,这里就不再贴了 Chef And His Characters 模拟题 Chef And The Pat ...

  3. CodeChef February Challenge 2018 Broken Clock (三角函数推导 + 矩阵快速幂)

    题目链接  Broken Clock   中文题面链接 令$cos(xα) = f(x)$ 根据三角函数变换公式有 $f(x) = \frac{2d}{l} f(x-1) - f(x-2)$ 我们现在 ...

  4. Codechef October Challenge 2018 游记

    Codechef October Challenge 2018 游记 CHSERVE - Chef and Serves 题目大意: 乒乓球比赛中,双方每累计得两分就会交换一次发球权. 不过,大厨和小 ...

  5. Codechef September Challenge 2018 游记

    Codechef September Challenge 2018 游记 Magician versus Chef 题目大意: 有一排\(n(n\le10^5)\)个格子,一开始硬币在第\(x\)个格 ...

  6. Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal

    原文链接http://www.cnblogs.com/zhouzhendong/p/9010945.html 题目传送门 - Codechef STMINCUT 题意 在一个有边权的无向图中,我们定义 ...

  7. Codechef August Challenge 2018 : Chef at the River

    传送门 (要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来 结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解. 首先这个数量肯定是下界,更少的话连第一次都 ...

  8. Codechef August Challenge 2018 : Safe Partition

    传送门 (虽然是A了但是不知道复杂度是不是正确的 考虑以某个位置为结尾的合法划分 先考虑min,带来的影响是限制了最小长度,预处理出这个最小长度后,这可以在处理到这个数时,把不能算的部分去掉(不满足m ...

  9. Codechef August Challenge 2018 : Interactive Matrix

    传送门 首先整个矩阵可以被分为很多小矩阵,小矩阵内所有行的单调性是一样的,所有列的单调性是一样的. 考虑如何在这样一个小矩阵中找出答案.我的策略是每次取四个角中最大值和最小值的点,这样可以每次删掉一行 ...

  10. Codechef August Challenge 2018 : Lonely Cycles

    传送门 几波树形dp就行了. #include<cstdio> #include<cstring> #include<algorithm> #define MN 5 ...

随机推荐

  1. 网络架构,七层协议,三次握手四次挥手,socket套接字简单编程

    一.单机架构 应用领域: 植物大战僵尸 office 二.CS架构 应用领域: QQ 大型网络游戏 计算机发展初期用户去取数据,直接就去主机拿,从这里开始就分出了客户端和服务端. 客户端:用户安装的软 ...

  2. RocketMQ高性能原理(pushConsumer,CommitLog,ZeroCopy)

    1. Rocketmq消费模型(实时性) 常见的数据同步方式有这几种: push:producer发送消息后,broker马上把消息投递给consumer.这种方式好在实时性比较高,但是会增加brok ...

  3. 13.AutoMapper 之映射前后(Before and After Map Action)

    https://www.jianshu.com/p/1ff732094f21 映射前后(Before and After Map Action) 你可能偶尔需要在映射发生前后执行自定义逻辑.这应该很少 ...

  4. char转int,int转char

    char转int 1) '; if (Character.isDigit(ch)){ // 判断是否是数字 int num = Integer.parseInt(String.valueOf(ch)) ...

  5. 位操作符:&位与、|位或、^异或、~求反、<<左移位、>>带符号右移位、>>>无符号右移位

    . 操作符 名称 实例(例中使用字节) 描述 & 位与 10101110 & 10010010 得到10000010 两个相应位上比特如果都为1,则执行 与 操作会得到1 | 位或 1 ...

  6. docker 安装与使用的相关问题

    Error response from daemon: i/o timeout $ sudo docker search centos Error response from daemon: Get ...

  7. DNS域名工作原理及解析

    0x00 定义 DNS( Domain Name System)是“域名系统”的英文缩写,它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网.DNS使用TCP和UDP端口53 ...

  8. Spring加载资源文件的方式

    UrlResource 封装了java.net.URL,它能够被用来访问任何通过URL可以获得的对象,例如:文件.HTTP对象.FTP对象等.所有的URL都有个标准的 String表示,这些标准前缀可 ...

  9. win32创建工具栏的自定义图标

    注意点:使用LoadImage函数加载bmp图片,这里特指BMP图片,其实LoadImage可以加载很多格式的图片 HBITMAP bitmap = (HBITMAP)LoadImage((HINST ...

  10. 前端每日实战:157# 视频演示如何用纯 CSS 创作一个棋盘错觉动画(实际上每一行都是平行的)

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/VEyoGj 可交互视频 此视频是可 ...