hdu多校第一场 1013(hdu6590)Code 凸包交
题意:
给定一组(x1,x2,y),其中y为1或0,问是否有一组(w1,w2,b),使得上述的每一个(x1,x2,y)都满足x1*w1+x2*w2+b在y=1时大于0,在y=-1时小于0.
题解:
赛时想的是半平面交,wa到哭
后来看题解,居然那么简单?
我们把x1,x2看成两个坐标轴,那么其实(w1,w2,b)对应着一条直线,x1*w1+x2+w2+b=0,那么令这个值大于0的必定在这条直线一边,令这个值小于0的必定在这个直线另一边。这道题也就是在问,有没有一条线能分隔开这两种点。
那么把这两组点分别求出凸包,再去判断凸包有没有交就行了。注意,如果点在线上,那么上述式子算出来就得0了,因此两个凸包必须严格不交,点或边重合也不行。
代码:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
typedef pair<int,int> pii;
const int inf = 0x3f3f3f3f;
const int N =1e5+;
#define clc(a,b) memset(a,b,sizeof(a))
const double eps = 1e-;
const int MOD = 1e9+;
void fre() {freopen("in.txt","r",stdin);}
void freout() {freopen("out.txt","w",stdout);}
inline int read() {int x=,f=;char ch=getchar();while(ch>''||ch<'') {if(ch=='-') f=-;ch=getchar();}while(ch>=''&&ch<='') {x=x*+ch-'';ch=getchar();}return x*f;} int sgn(double x) {
if(fabs(x) < eps)return ;
if(x < )return -;
else return ;
} struct Point {
int x,y;
Point() {}
Point(int _x,int _y) {
x = _x;
y = _y;
}
Point operator -(const Point &b)const {
return Point(x - b.x,y - b.y);
}
int operator ^(const Point &b)const {
return x*b.y - y*b.x;
}
int operator *(const Point &b)const {
return x*b.x + y*b.y;
}
friend int dis2(Point a) {
return a.x*a.x+a.y*a.y;
}
friend bool operator<(const Point &a,const Point &b){
if(fabs(a.y-b.y)<eps) return a.x<b.x;
return a.y<b.y;
}
};
typedef Point Vector;
double Dot(Point A, Point B){return A.x*B.x+A.y*B.y;}//点积
double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}//叉积
double Length(Vector A){return sqrt(Dot(A,A));}//OA长
double Angle(Point A,Point B){return acos(Dot(A,B)/Length(A)/Length(B));}//OA和OB的夹角
//判断线段相交,不在端点相交
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2){
double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
return sgn(c1)*sgn(c2)<&&sgn(c3)*sgn(c4)<;
} int graham(Point p[],int n,Point q[]){
int top=;
sort(p,p+n);
if(n==) return ;
q[]=p[];
if(n==) return ;
q[]=p[];
if(n==) return ;
q[]=p[];
for(int i=;i<n;i++){
while(top&&(Cross(q[top]-q[top-],p[i]-q[top-])<=)) top--;
q[++top]=p[i];
}
int len=top;
q[++top]=p[n-];
for(int i=n-;i>=;i--){
while(top!=len&&(Cross(q[top]-q[top-],p[i]-q[top-])<=)) top--;
q[++top]=p[i];
}
return top;
} bool C_S(Point *ch1,int t1,Point *ch2,int t2)//判断凸包是否相交
{
double angle[],x;
int i,j,k,m;
if(t1==)return true;
if(t1==)
{
for(i=;i<t2;i++)
{
k=sgn(Cross(ch1[]-ch1[],ch2[i]-ch1[]));
if(k==&&Dot(ch1[]-ch1[],ch2[i]-ch1[])>)
{
if(Length(ch2[i]-ch1[])<Length(ch1[]-ch1[]))break;
}
}
if(i<t2)return false;
if(t2==&&SegmentProperIntersection(ch1[],ch1[],ch2[],ch2[]))return false;
return true;
}
angle[]=;
for(i=;i<t1;i++)
angle[i-]=Angle(ch1[]-ch1[],ch1[i]-ch1[]);
for(i=;i<t2;i++)
{
j=sgn(Cross(ch1[]-ch1[],ch2[i]-ch1[]));
if(j<||(j==&&Dot(ch1[]-ch1[],ch2[i]-ch1[])<))continue;
j=sgn(Cross(ch1[t1-]-ch1[],ch2[i]-ch1[]));
if(j>||(j==&&Dot(ch1[t1-]-ch1[],ch2[i]-ch1[])<))continue;
x=Angle(ch1[]-ch1[],ch2[i]-ch1[]);
m=lower_bound(angle,angle+t1-,x)-angle;
if(m==)j=;
else j=m-;
k=sgn(Cross(ch1[j+]-ch2[i],ch1[j+]-ch2[i]));
if(k>=)break;
}
if(i<t2)return false;
return true;
} Point p1[],p2[],ch1[],ch2[];
int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
int cnt1=,cnt2=;
for(int i=;i<n;i++){
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
if(c==){
p1[cnt1++]=Point(x,y);
}
else p2[cnt2++]=Point(x,y);
}
int t1=graham(p1,cnt1,ch1);
int t2=graham(p2,cnt2,ch2);
if(C_S(ch1,t1,ch2,t2)&&C_S(ch2,t2,ch1,t1)) printf("Successful!\n");
else printf("Infinite loop!\n");
}
}
hdu多校第一场 1013(hdu6590)Code 凸包交的更多相关文章
- hdu 多校第一场
1001 思路:打表可以发现只有3|n 和 4|n 的情况有解,判一下就好啦. #include<bits/stdc++.h> #define LL long long #define f ...
- hdu多校第一场 1006 (hdu6583)Typewriter dp/后缀自动机
题意: 有个打字机,在当前字符串后新加一个字花费p,把当前字符串的一个连续子串拷贝到当前字符串的末尾花费q,给定一个字符串,求用打字机打出这个字符串的最小花费. 题解: 容易想到用dp 记dp[i]为 ...
- hdu多校第一场1003 (hdu6580)Milk 背包
题意: 有一个n*m的矩阵,左右可以随便走,但只能在每一行的中点往下走,每走一格花费时间1. 现在这个矩阵里放了k瓶牛奶,第i个牛奶喝下去需要ti时间 起点是(1,1) 对于每个i∈[1,k],问喝掉 ...
- hdu多校第一场1005(hdu6582)Path 最短路/网络流
题意: 在无向图上删边,让此图上从起点到终点的最短路长度变大,删边的代价是边长,求最小代价. 题解: 先跑一遍迪杰斯特拉,求出所有点的d[]值,然后在原图上保留所有的边(i,j)仅当i,j满足d[j] ...
- hdu多校第一场1004(hdu6581)Vacation 签到
题意:有n+1辆车,每辆车都有一定的长度,速度和距离终点的距离,第1-n辆车在前面依次排列,第0辆车在最后面.不允许超车,一旦后车追上前车,后车就减速,求第0辆车最快什么时候能到达终点? 思路:对于每 ...
- HDU6581 Vacation (HDU2019多校第一场1004)
HDU6581 Vacation (HDU2019多校第一场1004) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6581 题意: 给你n+1辆汽车, ...
- 2019牛客多校第一场 I Points Division(动态规划+线段树)
2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...
- 牛客多校第一场 B Inergratiion
牛客多校第一场 B Inergratiion 传送门:https://ac.nowcoder.com/acm/contest/881/B 题意: 给你一个 [求值为多少 题解: 根据线代的知识 我们可 ...
- 2019年牛客多校第一场B题Integration 数学
2019年牛客多校第一场B题 Integration 题意 给出一个公式,求值 思路 明显的化简公式题,公式是分母连乘形式,这个时候要想到拆分,那如何拆分母呢,自然是裂项,此时有很多项裂项,我们不妨从 ...
随机推荐
- ARM 汇编 数据处理指令
一. 如何把数据放到寄存器中 1. 数据搬移指令 mov , mvn 1) 指令格式:<opcode><cond>{s} Rd, operand <操作 ...
- 安装apache的注意事项
在安装apache的时候我们一般都会用yum一键安装,但是很少去考虑相关的依赖包有什么,所以今天特意做一个记录,方便以后编译安装的时候,进展顺利. yum install httpd Installi ...
- centos8 安装vmware需要的内核头文件 kernel-headers.
centos8 安装vmware需要的内核头文件 kernel-headers. uname -r (查看内核版本) rpm -qa kernel-headers (查看kernel-headers版 ...
- CodeForces祝贺上紫
还是靠手速了. 不少比赛,经常差几分钟/一个细节就能AC一道比较难的题目. 加油! P.S 只能当成休闲性质,不能再当成正业了.迈向科研...
- Dubbox框架和Zookeeper 依赖的引入
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- Python 爬取赶集网租房信息
代码已久,有可能需要调整 #coding:utf-8 from bs4 import BeautifulSoup #有这个bs4不用正则也可以定位要爬取的内容了 from urlparse impor ...
- Delphi全面控制Windows任务栏
使用Windows95/NT/98操作系统的用户知道:Windows正常启动后,在电脑屏幕下方出现一块 任务栏.从系统功能角度而言,整个任务栏包括几个不同的子区域,从左至右依次是:开始 按钮.应用程序 ...
- Linux date命令 crontab每个月最后一天
###使用date获取日期时间等 # 当前日期 openstack@ubuntu:~$ date 2019年 01月 15日 星期二 15:10:49 CST # 明天 openstack@ubunt ...
- LeetCode 852. Peak Index in a Mountain Array (山脉数组的峰顶索引)
题目标签:Binary Search 题目给了我们一组 int array,让我们找到数组的 peak. 利用 binary search, 如果数字比它后面那个数字小,说明还在上坡,缩小范围到右半边 ...
- 拾遗:不用使 sizeof 获取数组大小
... #include <stdio.h> #include <unistd.h> int main(void) { ] = {}; size_t num = () - (i ...