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

    一.初识springboot 个人总结:springboot是一个开发更加便捷的spring的技术框架,通过引入启动器便可以快捷的让spring框架和其他框架进行整合, springboot很容易上手 ...

  2. 设计模式之单例模式(Singleton Pattern)

    单例模式是最简单的设计模式之一.属于创建型模式,它提供了一种创建对象的最佳方式.使应用中只存在一个对象的实例,并且使这个单实例负责所有对该对象的调用.这种模式涉及到一个单一的类,该类负责创建自己的对象 ...

  3. python中几个常见的魔法方法

    首先,什么是魔法方法呢?在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做"魔法"方法. __ init__()方法 当一个实例被创建的时候调用的初始 ...

  4. 在springboot中集成jsp开发

    springboot就是一个升级版的spring.它可以极大的简化xml配置文件,可以采用全注解形式开发,一个字就是很牛.在springboot想要使用jsp开发,需要集成jsp,在springboo ...

  5. ubuntu部署Java、Python开发环境

    要部署Java开发环境首先就要安装JDK. 一.安装JDK8 1. 下载 jdk-8u172-linux-x64.tar.gz 到 /usr/java8/ 目录下: 2. tar  -zxvf  jd ...

  6. MySQL数据库数据类型以及INT(M)的含义

    nt(M)我们先来拆分,int是代表整型数据那么中间的M应该是代表多少位了,后来查mysql手册也得知了我的理解是正确的,下面我来举例说明.   MySQL 数据类型中的 integer types ...

  7. iPad和iPhone上的应用程序图标

    iPad和iPhone上的应用程序图标 问:如何在iPad和iPhone使用我的应用程序包中的图标文件? 答:下面是处理文件的图标为iPhone专用的应用程序,iPad的专用应用程序,以及通用的应用程 ...

  8. axios 请求常用组件,及其错误

    1. var nodeModules = path.join(processPath, 'node_modules') var querystring = require(nodeModules + ...

  9. python自动化测试—配置文件的使用

    一.什么是配置文件? 配置文件示例 [mysql] default-character-set = utf8 [mysqld] port = 3306 basedir = c:\mysql-5.7.2 ...

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

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