[几何 扫描线] LOJ#6260. 「CodePlus 2017 12 月赛」寄蒜几盒

直线很少,把交点算出来扫描线

多边形的数量是 O(n2) O ( n 2 ) 的,因为是平面图,所以顶点的总数也是 O(n2) O ( n 2 ) 的,搞一搞就好了

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#define eq(a,b) (fabs(a-b)<eps)
#define IN(x) ((x)>=-L && (x)<=L)
#define pb push_back

using namespace std;

typedef double ld;

const int N=510,M=1000010;
const ld eps=1e-7;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &x){
  char c=nc(); x=0;
  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

inline void read(ld &x){
  char c=nc(); int f=1,flg=0,dv=1; x=0;
  for(;c>'9'||c<'0';c=nc())if(c=='-')f=-1;
  for(;c>='0'&&c<='9' || c=='.';x=x*10+c-'0',c=nc(),dv=flg?dv*10:dv)
    if(c=='.'){
      flg=1; c=nc();
    }
  x/=dv; x*=f;
}

ld L,l,r;
int cnt,tot,t,n,m,id[N];
ld A[N],B[N],C[N];

struct Point{
  ld x,y;
  Point(ld _x=0,ld _y=0):x(_x),y(_y){}
  friend bool operator <(const Point &a,const Point &b){
    if(a==b) return 0;
    if(!eq(a.x,b.x)) return a.x<b.x;
    return a.y<b.y;
  }
  friend bool operator ==(const Point &a,const Point &b){
    return eq(a.x,b.x) && eq(a.y,b.y);
  }
};

struct node{
  Point x; int g,a,b;
  friend bool operator <(const node &a,const node &b){
    if(a.x==b.x) return a.a<b.a;
    return a.x<b.x;
  }
}a[M];

vector<ld> border; 
vector<Point> polygon[M];

inline Point Cross(int x,int y){
  ld k1=-A[x]/B[x],d1=-C[x]/B[x],k2=-A[y]/B[y],d2=-C[y]/B[y];
  if(eq(k1,k2)) return Point(-1e20,-1e20);
  Point ret; ret.x=(d1-d2)/(k2-k1); ret.y=k1*ret.x+d1;
  return ret;
}

int ans[M];

inline ld f(int g,ld x){
  return -(A[g]*x+C[g])/B[g];
}

inline bool cmp(const int &a,const int &b){
  if(!eq(f(a,l),f(b,l))) return f(a,l)<f(b,l);
  return -A[a]/B[a]>-A[b]/B[b];
}

int p=1,rk[N],pnum[N];

inline void work(){
  for(int i=1;i<t;i++){
    ++cnt;
    polygon[cnt].pb(Point(l,f(id[i],l)));
    polygon[cnt].pb(Point(l,f(id[i+1],l)));
    pnum[i]=cnt;
  }
  for(;p<=tot;p++){
    if(a[p].x.x>r) break;
    if(a[p].g){
      int l=1,r=t,res,mid;
      while(l<=r) f(id[mid=l+r>>1],a[p].x.x)<a[p].x.y?l=(res=mid)+1:r=mid-1;
      ans[a[p].g]=pnum[res];
      continue;
    }
    int np=p,revL=min(rk[a[p].a],rk[a[p].b]),revR=max(rk[a[p].a],rk[a[p].b]);
    while(np<tot && a[np+1].x==a[p].x){
      np++;
      revL=min(min(rk[a[np].a],rk[a[np].b]),revL);
      revR=max(max(rk[a[np].a],rk[a[np].b]),revR);
    }
    if(pnum[revL-1])
      polygon[pnum[revL-1]].pb(a[p].x);
    if(pnum[revR])
      polygon[pnum[revR]].pb(a[p].x);
    reverse(id+revL,id+revR+1);
    for(int i=revL;i<=revR;i++){
      rk[id[i]]=i;
      if(i==revR) break;
      polygon[pnum[i]].pb(a[p].x);
      pnum[i]=++cnt;
      polygon[cnt].pb(a[p].x);
    }
    p=np;
  }
  for(int i=1;i<t;i++){
    polygon[pnum[i]].pb(Point(r,f(id[i],r)));
    polygon[pnum[i]].pb(Point(r,f(id[i+1],r)));
  }
}

ld size[M];
int vis[M];

Point s;

inline bool cmp1(const Point &a,const Point &b){
  return (a.y-s.y)*(b.x-s.x)<(b.y-s.y)*(a.x-s.x);
}

inline ld cross(const Point &a,const Point &b){
  return (a.x-s.x)*(b.y-s.y)-(a.y-s.y)*(b.x-s.x);
}

inline ld calc(int x){
  vector<Point> &c=polygon[x];
  for(int i=1;i<c.size();i++)
    if(c[i]<c[0]) swap(c[i],c[0]);
  s=c[0]; sort(c.begin()+1,c.end(),cmp1);
  ld ret=0;
  for(int i=1;i<c.size()-1;i++)
    ret+=cross(c[i],c[i+1]);
  return ret/2;
}

void PutAns(int x){
  if(x>=10) PutAns(x/10); putchar(x%10+'0');
}

int main(){
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  read(n); read(m); read(L);
  for(int i=1;i<=n;i++){
    read(A[i]); read(B[i]); read(C[i]);
    if(!eq(B[i],0))
      id[++t]=i;
    else if(IN(C[i]/A[i]))
      border.pb(-C[i]/A[i]);
  }
  id[++t]=n+1; A[n+1]=0; B[n+1]=1; C[n+1]=L;
  id[++t]=n+2; A[n+2]=0; B[n+2]=1; C[n+2]=-L;
  border.pb(-L); border.pb(L);
  sort(border.begin(),border.end());
  l=-L; sort(id+1,id+1+t,cmp);
  for(int i=1;i<=t;i++) rk[id[i]]=i;
  for(int i=1;i<=t;i++)
    for(int j=i+1;j<=t;j++){
      Point cur=Cross(id[i],id[j]);
      //printf("%d %d %.2lf %.2lf\n",i,j,cur.x,cur.y);
      if(!IN(cur.x)) continue;
      ++tot; a[tot].x=cur; a[tot].a=id[i]; a[tot].b=id[j]; a[tot].g=0;
    }
  for(int i=1;i<=m;i++){
    ++tot; read(a[tot].x.x); read(a[tot].x.y);
    a[tot].g=i;
  }
  sort(a+1,a+1+tot);
  for(int i=0;i<border.size()-1;i++){
    l=border[i]; r=border[i+1];
    if(eq(l,r)) continue;
    work();
  }
  /*for(int i=1;i<=cnt;i++){
    printf("%d : ",i);
    for(auto x : polygon[i]) printf("%.2lf %.2lf\n",x.x,x.y);
    putchar('\n');
    }*/
  for(int i=1;i<=m;i++){
    if(!vis[ans[i]])
      vis[ans[i]]=1,size[ans[i]]=calc(ans[i]);
    PutAns((int)(size[ans[i]]+0.005)); putchar('.');
    int r=(long long)(size[ans[i]]*100+0.5)%100;
    if(r<10) putchar('0');
    PutAns(r); putchar('\n');
    //printf("%.2lf\n",size[ans[i]]);
  }
  return 0;
}
基于STM32F407,使用DFS算法实现最短迷宫路径检索,分为三种模式:1.DEBUG模式,2. 训练模式,3. 主程序模式 ,DEBUG模式主要分析bug,测量必要数据,训练模式用于DFS算法训练最短路径,并将最短路径以链表形式存储Flash, 主程序模式从Flash中….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值