7.1 NOI模拟赛 凸包套凸包 floyd 计算几何
计算几何之所以难学 就是因为太抽象了 不够直观 而且情况很多 很繁琐 甚至有一些东西不清不楚。。
这道题注意到题目中的描述 一个鸽子在两个点所连直线上也算。
通过看题解 发现这个地方并非直线而是线段 这不是明摆着坑人..
先考虑m<=10的做法 可以想到爆搜 然后 就利用直线 点 三角形来判断复杂度\(2^m\cdot m^3\cdot n\) 期望得分30.
其中直线判断的时候 严谨一点是 如果在直线上再判断len的大小 可是当时考试的时候发现题目中的这句话了所以就没管。
三角形 的话容易转圈叉积来判 三个叉积同方向就说明在三角形中。
code bf:
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-8
#define sq sqrt
#define mod 1000000007
#define S second
#define F first
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=300010,maxn=10000010;
int n,m,cnt,ans=INF;
int a[MAXN];
struct wy
{
int x,y;
inline bool operator ==(wy a)
{
return x==a.x&&y==a.y;
}
inline wy operator -(wy a)
{
return (wy){x-a.x,y-a.y};
}
}t[MAXN],w[MAXN];
inline int judge(wy a,wy b)
{
ll ww=(ll)a.x*b.y-(ll)b.x*a.y;
if(!ww)return 0;
return ww>0?1:-1;
}
int b[MAXN];
inline void dfs(int x,int v)
{
if(v>=ans)return;
if(x==m+1)
{
rep(1,n,w1)
{
int flag=0;
rep(1,v,i)
{
if(t[w1]==w[b[i]]){flag=1;break;}
rep(i+1,v,j)
{
if(t[w1]==w[b[j]]){flag=1;break;}
//判断点是否在一条直线上:
if(!judge(w[b[i]]-w[b[j]],t[w1]-w[b[j]])){flag=1;break;}
rep(j+1,v,k)
{
if(t[w1]==w[b[k]]){flag=1;break;}
//判断点是否在一个三角形中 要求叉积的值都相等.
int c1=judge(w[b[i]]-w[b[j]],t[w1]-w[b[j]]);
int c2=judge(w[b[k]]-w[b[i]],t[w1]-w[b[i]]);
int c3=judge(w[b[j]]-w[b[k]],t[w1]-w[b[k]]);
if(c1==c2&&c2==c3){flag=1;break;}
}
if(flag)break;
}
if(flag)break;
}
if(!flag)return;
}
ans=v;
return;
}
b[v+1]=x;
dfs(x+1,v+1);
dfs(x+1,v);
}
int main()
{
freopen("lo.in","r",stdin);
freopen("lo.out","w",stdout);
get(n);get(m);
rep(1,n,i)
{
int get(x),get(y);
t[i]=(wy){x,y};
}
rep(1,m,i)
{
int get(x),get(y);
w[i]=(wy){x,y};
}
if(m<=10)
{
dfs(1,0);
put(ans==INF?-1:ans);
return 0;
}
put(-1);
return 0;
}
值得注意的是叉积的时候要开longlong. 不然痛失30分。
进一步考虑 如果是线段而不是直线的话 那么其实由暴力来看就是一些三角形 一些直线 一些点构成了答案。
这些东西其实只需要把鸽子所围成的凸包上的点都包含其实相当于包含了整体。因为这些点之间连边形成的一定也是一个凸多边形。
其实就是要求找到一个凸包包含另外一个凸包。
这个时候 考虑每一个点 然后向原凸包中发出两条切线显然切线一侧的可以是后继 然后连边。
最后跑floyd即可。最后从i到i的环的最小值就是答案了。
分析出问题的关键还是从答案的角度考虑:显然答案的点一定不在原凸包内 那只能在凸包外 此时找凸包外一点 然后寻找下一点 其实就是做切线问题了。
值得一提的是 该特判的特判好 不过没有特判一个点的情况 且是在线段的情况下的。
code sol:
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 100000000
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-9
#define sq sqrt
#define mod 998244353
#define S second
#define F first
#define pf(x) ((x)*(x))
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=100010,maxn=510;
int n,m;
int f[maxn][maxn];
struct Vec
{
db x,y;
bool operator ==(Vec b){return fabs(x-b.x)<=EPS&&fabs(y-b.y)<=EPS;}
db operator %(Vec b){return x*b.y-y*b.x;}
inline void ni(){x=-x;y=-y;}
Vec operator -(Vec b){return (Vec){x-b.x,y-b.y};}
}a[MAXN],b[maxn];
typedef Vec P;
inline int pd(db x,db y){return fabs(x-y)<=EPS?0:x<y?-1:1;}
int main()
{
freopen("1.in","r",stdin);
get(n);get(m);
memset(f,0x3f,sizeof(f));
rep(1,n,i)get(a[i].x),get(a[i].y);
rep(1,m,i)get(b[i].x),get(b[i].y);
rep(1,m,i)
{
int mxid=0,mnid=0,id1=0,id2=0;
P mx,mn,tmp;db v1,v2;
rep(1,n,j)
{
if(a[j]==b[i])continue;
tmp=a[j]-b[i];
db ww=tmp%(a[1]-b[i]);
if(mxid==0||pd(tmp%mx,0)<0)mx=tmp,mxid=j;
if(mnid==0||pd(tmp%mn,0)>0)mn=tmp,mnid=j;
if(id1==0||v1<ww)id1=j,v1=ww;
if(id2==0||v2>ww)id2=j,v2=ww;
}
if(pd((a[id1]-b[i])%(a[id2]-b[i]),0)<0)continue;
mx.ni();
rep(1,m,j)
{
if(i==j)continue;
tmp=b[j]-b[i];
if(pd(mn%tmp,0)<=0&&pd(tmp%mx,0)<=0)f[i][j]=1;
}
}
rep(1,m,k)rep(1,m,i)rep(1,m,j)f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
int ans=INF;rep(1,m,i)ans=min(ans,f[i][i]);
put(ans==INF?-1:ans);
return 0;
}
7.1 NOI模拟赛 凸包套凸包 floyd 计算几何的更多相关文章
- 【2019.3.20】NOI模拟赛
题目 这里必须标记一下那个傻逼问题,再不解决我人就没了! 先放一个 $T3$ $20$ 分暴力 #include<bits/stdc++.h> #define rep(i,x,y) for ...
- NOI模拟赛 Day1
[考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...
- 6.28 NOI模拟赛 好题 状压dp 随机化
算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...
- 【2018.12.10】NOI模拟赛3
题目 WZJ题解 大概就是全场就我写不过 $FFT$ 系列吧……自闭 T1 奶一口,下次再写不出这种 $NTT$ 裸题题目我就艹了自己 -_-||| 而且这跟我口胡的自创模拟题 $set1$ 的 $T ...
- NOI 模拟赛 #2
得分非常惨惨,半个小时写的纯暴力 70 分竟然拿了 rank 1... 如果 OYJason 和 wxjor 在可能会被爆踩吧 嘤 T1 欧拉子图 给一个无向图,如果一个边集的导出子图是一个欧拉回路, ...
- NOI模拟赛Day5
T1 有and,xor,or三种操作,每个人手中一个数,求和左边进行某一种运算的最大值,当t==2时,还需要求最大值的个数. test1 20% n<=1000 O(n^2)暴力 test2 2 ...
- NOI模拟赛Day4
看到成绩的时候我的内心** woc第一题写错了呵呵呵呵呵呵呵呵 人不能太浪,会遭报应的** ------------------------------------------------------ ...
- NOI模拟赛Day3
终于A题啦鼓掌~开心~ 开考看完题后,觉得第二题很好捏(傻叉上线 搞到十一点准备弃疗了然后突然发现我会做第一题 于是瞎码了码,就去准备饭票了... 好了,停止扯淡(就我一个我妹子每天不说话好难受QAQ ...
- NOI模拟赛Day2
深深的感受到了自己的水 ---------------------------------------------------------------------------------------- ...
随机推荐
- Cow Relays,过N条边的最短路
题目链接 题意: 找从a到b的经过N条边的最短路 分析: 有点板子...方法:矩阵存,然后有个类似快速幂的思想,然后再加上离散化就好了. 没啥写的,只能说说矩阵了,我用的方法是先枚举i,j再枚举k,当 ...
- Python-日期格式化
1.基本方法 获取当前日期:time.time() 获取元组形式的时间戳:time.local(time.time()) 格式化日期的函数(基于元组的形式进行格式化): (1)time.asctime ...
- CSS3 实现复杂的背景图案
灵活的背景定位 实现效果: 将背景图定位到距离容器底边 10px 且距离右边 20px 的位置. background-position 方案 代码: <div>海盗密码</div& ...
- HDFS读写流程(重点)
@ 目录 一.写数据流程 举例: 二.异常写流程 读数据流程 一.写数据流程 ①服务端启动HDFS中的NN和DN进程 ②客户端创建一个分布式文件系统客户端,由客户端向NN发送请求,请求上传文件 ③NN ...
- C++左值引用与右值引用
本文翻译自:https://docs.microsoft.com/en-us/cpp/cpp/references-cpp?view=vs-2019 引用,类似于指针,用于存储一个位于内存某处的对象的 ...
- www.215wd.com
www.215wd.com 传奇销售系统 QQ:1479528000
- Python网络编程03 /缓存区、基于TCP的socket循环通信、执行远程命令、socketserver通信
Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命令.socketserver通信 目录 Python网络编程03 /缓存区.基于TCP的socket循环通信.执行远程命 ...
- python小游戏-水文
脚本不会,全都白费.所以就去学习了简单的python,结果不慎学了python中的pygame,浪费了不少时间,没啥用如果不做游戏个人觉得最好别学,学爬虫她不香吗?不过也有一点收获,打飞机小游戏,源码 ...
- 问题:win10缺少一个或多个网络协议
国庆回家,家里电脑连不上网了,诊断给出的结果是“缺少一个或多个网络协议” 网上这类问题提问的不少,回答的方法也是各种各样,一个一个试下来,发现这个方法是可行的. 1.打开设置--网络和Internet ...
- 集训作业 洛谷P1443 马的遍历
这个题是个搜索,而且有是最少的步数,肯定就是广搜啦,不知道为什么的同学先去学习一下广搜吧. 养成好习惯,看见最少步数就去想想广搜(只是我自己觉得) 竟然这个题可以如此顺畅的想到广搜,感觉不难啊,但还有 ...