链接: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. Java 将Maven项目打成可执行jar包

    一.用maven-shade-plugin打包 在pom.xml文件中加入如下信息,利用Maven的maven-shade-plugin插件进行打包. <build> <plugin ...

  2. [BJWC2008] Gate Of Babylon

    题目链接 容斥+隔板法+Lucas定理 #include <bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m, ...

  3. selenium与页面交互之二:webelement类的属性

    webelement类的属性如下: element.size()   获取元素的大小 element.tag_name() 获取元素的HTML标签名称 element.text()   获取元素的文本 ...

  4. 新版 Scrapy 中 sys.conf.settings 的替代方法

    新版 Scrapy 中 sys.conf.settings 的替代方法 在 scrapy 项目目录下,有个 settings.py 文件,此文件是用来存放爬虫项目的各种配置,比如说 MongoDB 的 ...

  5. linux相关命令大全......持续更新

    启动项目8080端口被占用,然而老久没玩Linux,命令忘光了,杀死进程都不记得了. 决定整理一波吧....... Linux: sudo强制执行,不在root用户下时使用. top 相当于windo ...

  6. crm---本项目的权限控制模式

    一:url权限:  最底层的权限控制,,缺点在与没有预判的机制,造成客户体验下降.           前提: 为controller中的每一个方法(即资源)定义一个资源(Resource)名称,,该 ...

  7. elementui 之el-pagination爬坑,属性pager-count的设定

    我想设置总页数为10页,页码条总是显示两个页码,其余省略号显示,我选择了pager-count,如下: <el-pagination @size-change="handleSizeC ...

  8. Redox OS 发布 0.5 版

    Redox OS 是一个几乎完全以 Rust 语言编写的通用操作系统及周围生态(例如文件系统.显示服务器及 Rust 版本的 libc).其遵循微内核架构,在一定程度上兼容于 POSIX. 该项目于日 ...

  9. 关于sharekey 与Open system+wep

    Open_system+wep与open_system的区别在于: 对于开放系统认证,在设置时启用WEP,此时,WEP用于在传输数据时加密,对于认证没有任何作用. 抓包open_system+wep: ...

  10. 线段树优化建图 || CF786B Legacy

    题面:786B - Legacy 代码: #include<cstdio> #include<cstring> #include<iostream> #includ ...