嘻嘻嘻嘻,从读题到过题大概一个小时?

这套题题面太长了。。。就挑短的写。。

题意很简单。   给出平面上n个点,求一个面积最小的平行四边形覆盖这n个点。

显然要先求凸包。

然后枚举边就可以了。我一开始脑子抽了,只枚举了相邻的。。(今天下午四点多才吃上早饭很痛苦。感觉神智不清,昨晚补题补到3点。。。)

然后我们要 分别找出 离这两条边最远的 点吧,然后通过简单的平移操作求直线交点,再用叉积搞一下就阔以了。

虽然理论上 n^3不会t,但我还是t了。。。所以我们先预处理出来离每条边最远的点是哪一个。就阔以了。

记得特判一下没有凸包的情况,虽然不知道有没有这种数据。。。

 #include <bits/stdc++.h>
using namespace std;
typedef double db;
const db eps=1e-;
const db pi=acos(-);
int sign(db k){
if (k>eps) return ; else if (k<-eps) return -; return ;
}
int cmp(db k1,db k2){return sign(k1-k2);}
struct point{
db x,y;
point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
point operator * (db k1) const{return (point){x*k1,y*k1};}
point operator / (db k1) const{return (point){x/k1,y/k1};}
db abs(){return sqrt(x*x+y*y);}
db dis(point k1){return ((*this)-k1).abs();}
point turn90(){ return point{-y,x};}
db getP()const { return sign(y)==||(sign(y)==&&sign(x)==-);}
point unit(){db w=abs(); return point{x/w,y/w};}
db abs2(){return x*x+y*y;}
bool operator < (const point k1) const{
int a=cmp(x,k1.x);
if (a==-) return ; else if (a==) return ; else return cmp(y,k1.y)==-;
}
};
db cross(point k1,point k2){ return k1.x*k2.y-k1.y*k2.x;}
db dot(point k1,point k2){ return k1.x*k2.x+k1.y*k2.y;}
db rad(point k1,point k2){ return atan2(cross(k1,k2),dot(k1,k2));}
int compareangle(point k1,point k2){
return k1.getP()<k2.getP()||(k1.getP()==k2.getP()&&sign(cross(k1,k2))>);
}
point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影
point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2());
}
point getLL(point k1,point k2,point k3,point k4){
db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3);
return (k1*w2+k2*w1)/(w1+w2);
}
struct line{
point p[];
line(point k1,point k2){p[]=k1;p[]=k2;}
point &operator[](int k){ return p[k];}
int include(point k){ return sign(cross(p[]-p[],k-p[])>);}
point dir(){ return p[]-p[];}
line push(db eps){//向左手边平移eps
//const db eps=1e-6;
point delta=(p[]-p[]).turn90().unit()*eps;
return {p[]-delta,p[]-delta};
}
};
point getLL(line k1,line k2){
return getLL(k1[],k1[],k2[],k2[]);
}
int parallel(line k1,line k2){ return sign(cross(k1.dir(),k2.dir()))==;}
int sameDir(line k1,line k2){
return parallel(k1,k2)&&sign(dot(k1.dir(),k2.dir()))==;
}
int operator <(line k1,line k2){
if(sameDir(k1,k2))return k2.include(k1[]);
return compareangle(k1.dir(),k2.dir());
}
int checkpos(line k1,line k2,line k3){ return k3.include(getLL(k1,k2));}
vector<point> convexHull(vector<point>ps){
int n = ps.size();if(n<=)return ps;
sort(ps.begin(),ps.end());
vector<point> qs(n*);int k=;
for(int i=;i<n;qs[k++]=ps[i++])
while (k>&&cross(qs[k-]-qs[k-],ps[i]-qs[k-])<=)--k;
for(int i=n-,t=k;i>=;qs[k++]=ps[i--])
while (k>t&&cross(qs[k-]-qs[k-],ps[i]-qs[k-])<=)--k;
qs.resize(k-);
return qs;
}
int t,n;
vector<point> p;point s1,t1,s2,t2;
map<pair<int,int>,int> mp;
db check(int a,int b,int c,int d){
int id1=mp[make_pair(a,b)],id2=mp[make_pair(c,d)];
s1=p[id1],s2=p[id1]+p[a]-p[b];
point t1 = getLL(p[c],p[d],s1,s2);//一个交点
s1 = p[id2],s2=p[id2]+p[c]-p[d];
point t2 = getLL(p[a],p[b],s1,s2);
point bb = getLL(p[a],p[b],p[c],p[d]);
db S = abs(cross(bb-t1,bb-t2));
return S;
}
void init(){
int m = p.size();
for(int i=;i<m;i++){
db mx = ;int id=-;
for(int j=;j<m;j++){
db tmp = p[j].dis(proj(p[i],p[(i+)%m],p[j]));
if(cmp(tmp,mx)>){
mx=tmp,id=j;
}
}
mp[make_pair(i,(i+)%m)]=id;
}
}
point tmp;
int main(){
scanf("%d",&t);
for(int cas=;cas<=t;cas++){
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%lf%lf",&tmp.x,&tmp.y);
p.push_back(tmp);
}
p=convexHull(p);
if(p.size()<){
printf("Swarm %d Parallelogram Area: 0.0000\n",cas);
continue;
}
init();
db ans = 1e15;
int m = p.size();
for(int i=;i<m;i++){
for(int j=i+;j<m;j++) {
ans = min(ans,check(i, (i + ) % m, j,(j+)%m));
}
}
printf("Swarm %d Parallelogram Area: %.4f\n",cas,ans);
p.clear();mp.clear();
}
}
/**
1
4
0 0
0 1
0 2
0 3
*/

gym101657 C的更多相关文章

随机推荐

  1. Windows远程桌面(mstsc)不能复制粘贴的解决办法

    原来通过mstsc远程连接Windows能够直接在本地和服务器之间复制.粘贴一些文字和文件,最近突然无法直接复制粘贴了,只能通过远程映射的本地磁盘方式交换文件,太为繁琐. 已经确认远程桌面连接选项“本 ...

  2. C# Draw multiple Lines

    I would make a Line class having start and end point of the line in struct Point and make list of th ...

  3. php 通过 create user 和grant 命令无法创建数据库用户和授权的解决办法

    php 通过 create user 和grant 命令无法创建数据库用户和授权的解决办法 解决办法, 通过 insert 命令的方式进行创建. 创建数据库用户: $sql= "insert ...

  4. redis批量删除key 远程批量删除key

    一.遇到的问题 在开发的过程中,经常会遇到要批量删除某种规则的key,如缓存的课程数据“course-课程uid”,其中课程uid是变量,我们需要删除"course-*"这一类的数 ...

  5. [开源]开放域实体抽取泛用工具 NetCore2.1

    开放域实体抽取泛用工具 https://github.com/magicdict/FDDC 更新时间 2018年7月16日 By 带着兔子去旅行 开发这个工具的起源是天池大数据竞赛,FDDC2018金 ...

  6. mybatis插入一个对象后获取表中自增的主键Id并且传入到插入的的对象中,方便将对象中其他属性赋值给其他以前表主键Id作为非空字段的表

    原本的sql语句为: <insert id="xx" parameterType="com.hrt.partner.model.ShopInsert"&g ...

  7. 【C#】C#线程_I/O限制的异步操作

    目录结构: contents structure [+] 为什么需要异步IO操作 C#的异步函数 async和await的使用 async和Task的区别 异步函数的状态机 异步函数如何转化为状态机 ...

  8. class<T>和 class<?>类型

    ? 表示不确定的java类型. T 表示java类型 Class<T>在实例化的时候,T要替换成具体类Class<?>它是个通配泛型,?可以代表任何类型<? extend ...

  9. jqGrid时间转换

    colModel: [ { label: '注册时间', name: 'createDate', index: 'create_date', width: 80, formatter:function ...

  10. 开源中文分词工具探析(七):LTP

    LTP是哈工大开源的一套中文语言处理系统,涵盖了基本功能:分词.词性标注.命名实体识别.依存句法分析.语义角色标注.语义依存分析等. [开源中文分词工具探析]系列: 开源中文分词工具探析(一):ICT ...