链接: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

Input

1
11
0 0
1 1
2 3
2 5
0 10
-2 10
-5 9
-8 7
-8 4
-6 1
-2 0 Output 0 1
////////////////////////////////////////////////////////////
看到这道题是一脸懵逼的,后来想着在每个端点附近是有四个点,至少有一个点在凸包内,最多每三个点共享一个凸包内相邻点,于是肯定可以做
那么对于一个点,怎么判断是否在凸包内呢,我是把每个端点求出跟左右两点的直线方程式(o1求)然后先对于每一个端点,对于凸包的端点,判断是在每一条线的那一侧(根据方程式用正负值来表示)
(但是不可能n²来求得对每个点来说,凸包端点是在线的哪一侧,所以我去了最上下左右四个点,用于判断,只要四个点是不同的,肯定至少有一个点跟判定点不共线,就可以求得是在哪一侧,后来发现出bug了
就是当最上下左右四个点指向的是两个点的时候,代码是有bug的,错误的例子就是左下右上处在最上下左右,这时候需要特判一下,如果出现了,将相同的值换成另外一个其他点就行了)
然后对于某个端点相邻的点,求出他在两条线的哪一侧,如果跟凸包端点都相同,那就是在凸包内了,后来想着,几十个点围成一个宽为1的正方形不就gg了,所以还加了对于上下左右四个点是否也符合条件
(后来问了zk的做法之后,发现,原来凸包是没有三点共线的吗,,,emmm我好菜)(前面会出现那个地方会出bug也是因为加了上下左右点的判定,但是这四个点集中在两个点的话,如果两点相邻,那么他们的方向值就是 0 0,这样
任何点都会被判定成不符合)
然后贴个自己的代码
///////////////////////////////////////////////////////////////////////////
 #include <bits/stdc++.h>
#define mst(a,b) memset((a),(b), sizeof a)
#define lowbit(a) ((a)&(-a))
#define IOS ios::sync_with_stdio(0);cin.tie(0);
using namespace std;
typedef long long ll;
const int mod=1e9+;
const int maxn=1e5+;
int n;
struct point{int x,y;};
struct line{ll a,b,c;};
point po[maxn];
line li[maxn][];
int cc[maxn][];
int dx[]={,,-,},dy[]={,-,,};
vector<pair<int,int> >ans;
int up=1e5+,down=1e5+,le=1e5+,ri=1e5+;
void gtline(int i,int j,line& k){
k.a=po[i].y-po[j].y;
k.b=po[j].x-po[i].x;
k.c=(ll)po[i].x*po[j].y-(ll)po[j].x*po[i].y;
} int dir(line&k,int x,int y){
ll g=k.a*x+k.b*y+k.c;
if(g==)return ;
if(g<)return -;
return ;
}
bool gg(int p,int x,int y){
if(dir(li[p][],x,y)!=cc[p][])return true;
if(dir(li[p][],x,y)!=cc[p][])return true;
return false;
}
bool ok(int p,int x,int y){
if(gg(p,x,y))return false;
if(gg(le,x,y))return false;
if(gg(ri,x,y))return false;
if(gg(up,x,y))return false;
if(gg(down,x,y))return false;
return true;
}
void co(){
int ne=n/;
set<pair<int,int> >use;
vector<int>kk;
if(ans.size()<ne){printf("-1\n");return;}
for(int i=;i<ans.size();++i){
if(!use.count(ans[i])){
use.insert(ans[i]);
kk.push_back(i);
--ne;
if(!ne)break;
}
}
if(ne){printf("-1\n");return;}
for(int i=;i<kk.size();++i){
printf("%d %d\n",ans[kk[i]].first,ans[kk[i]].second);
} }
void check(){
if(up==ri||up==le){
int tmp=1e5+;
for(int i=;i<n;++i)if(i!=ri&&i!=le){
if(po[i].y>po[tmp].y)tmp=i;
}
up=tmp;
}
if(down==ri||down==le){
int tmp=1e5+;
for(int i=;i<n;++i)if(i!=ri&&i!=le){
if(po[i].y<po[tmp].y)tmp=i;
}
down=tmp;
}
}
int main(){
#ifdef local
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int t;scanf("%d",&t);
po[up].y=-1e9-;po[down].y=1e9+;po[le].x=1e9+;po[ri].x=-1e9-;
while(t--){
up=1e5+,down=1e5+,le=1e5+,ri=1e5+;
scanf("%d",&n);
for(int i=;i<n;++i){
scanf("%d%d",&po[i].x,&po[i].y);
if(po[i].x<po[le].x)le=i;
if(po[i].x>po[ri].x)ri=i;
if(po[i].y>po[up].y)up=i;
if(po[i].y<po[down].y)down=i;
}
check();
for(int i=;i<n;++i){
for(int j=;j<;++j){
int ad=(j==?-:);
gtline(i,(i+ad+n)%n,li[i][j]);cc[i][j]=;
cc[i][j]=dir(li[i][j],po[le].x,po[le].y);
if(!cc[i][j])
cc[i][j]=dir(li[i][j],po[ri].x,po[ri].y);
if(!cc[i][j])
cc[i][j]=dir(li[i][j],po[up].x,po[up].y);
if(!cc[i][j])
cc[i][j]=dir(li[i][j],po[down].x,po[down].y);
}
}
ans.clear();
for(int i=;i<n;++i){
for(int j=;j<;++j){
if(ok(i,po[i].x+dx[j],po[i].y+dy[j])){
ans.push_back(make_pair(po[i].x+dx[j],po[i].y+dy[j]));
break;
}
}
}
co();
}
return ;
}

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

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

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

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

 #include <bits/stdc++.h>
#define mst(a,b) memset((a),(b), sizeof a)
#define lowbit(a) ((a)&(-a))
#define IOS ios::sync_with_stdio(0);cin.tie(0);
using namespace std;
typedef long long ll;
const int mod=1e9+;
const int maxn=1e5+;
int x[maxn],y[maxn];
vector<int>has[][];
vector<pair<int,int> >ans;
set<pair<int,int> >uu;
int main(){
#ifdef local
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
int t;scanf("%d",&t);
while(t--){
int n;scanf("%d",&n);
for(int i=;i<;++i)for(int j=;j<;++j)has[i][j].clear();
for(int i=;i<n;++i){
scanf("%d%d",&x[i],&y[i]);
has[abs(x[i])%][abs(y[i])%].push_back(i);
}
int a=,b=;
for(int i=;i<;++i)for(int j=;j<;++j)
if(has[i][j].size()>has[a][b].size())a=i,b=j;
int ne=n/; ans.clear(); uu.clear();
for(int i=;i<has[a][b].size();++i){
for(int j=i+;j<has[a][b].size();++j){
int l=has[a][b][i],r=has[a][b][j];
if(l+==r||l==&&r==n-)continue;
int mx=(x[l]+x[r])>>,my=(y[l]+y[r])>>;
if(!uu.count(make_pair(mx,my))){
ans.push_back(make_pair(mx,my));
uu.insert(make_pair(mx,my));
--ne;
}
if(!ne)break;
}
if(!ne)break;
}
for(int i=;i<ans.size();++i)printf("%d %d\n",ans[i].first,ans[i].second);
}
return ;
}

安慰一下自己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. python中的生成器、迭代器、闭包、装饰器

    迭代器 迭代是访问集合元素的一种方式.迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 可迭代对象 以直接作用于 for ...

  2. P1224 [NOI2013]向量内积

    传送门 发现这个内积和矩乘有点像,考虑构造一个 $n$ 行 $m$ 列的矩阵 $A$,每一行都是一个题目给定的 $m$ 维向量 设 $B=AA^T$ ,其中 $A^T$ 为 $A$ 的转置矩阵,那么对 ...

  3. RabbitMQ入门教程(一):安装和常用命令

    原文:RabbitMQ入门教程(一):安装和常用命令 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn ...

  4. 修改jar包package目录结构操作方法

    开发中会遇到用第三方的jar包,有时候会出现不同的jar包,包名一致的情况,这就会引发运行时异常,找不到相应的jar包. 这种问题时常困扰我们很长时间.下面提出一种解决办法,例如gson.jar. 1 ...

  5. vue学习之vue-resource的引入

    npm安装的命令 npm install vue-resource --save 安装完成后在main.js中导入 import  VueResource  from 'vue-resource' V ...

  6. scp 从另一台linux服务器拷贝文件或文件目录

    格式:scp [参数] [原路径] [目标路径] download 使用方法:scp -r root@127.0.0.1:/opt/soft/test /opt/soft/ scp -r 用户名@IP ...

  7. w、who、last、lastbon、lastlog显示登录命令用法

    一.w 显示已登录用户信息和用户正在执行命令 1.命令功能 w可以显示已登录系统的用户,并显示用户正在执行的命令 2.语法格式 w option user 选项说明 选项 选项说明 -h 不显示前两行 ...

  8. Django学习系列7:使用模板解决“不测试常量”规则,使用模板重构

    之前写的lists/tests.py中的单元测试,要查找特定的HTML字符串,但这不是测试HTML的高效方法. 单元测试规则之一“不测试常量”,编写断言检测HTML字符串中是否有制定的字符串序列,不是 ...

  9. regsvr32 驱动

    1.将SYS驱动文件放到系统目录的SYSTEM32目录中.2.按WIN+R组合键,在运行框中输入:regsvr32 sys所在全路径,点击确定即可.

  10. C#WinFrom导出Excel

    采用的是以DataGridView的形式导出,使用NPOI.dll 1.由于使用的是DataGridView,所以类需要创建在From的Project下,DLL导入NPOI 2.代码如下 using ...