• Gym 101917 E 简单计算几何,I 最大流


    题目链接 https://codeforces.com/gym/101917

    题意:给定一个多边形(n个点),然后逆时针旋转A度,然后对多边形进行规约,每个点的x规约到[0,w]范围内,y规约到[0,h]范围内,输出规约后的结果。

    解析:求出来 多边形的长和宽,再和w,h比较,对点按比例进行缩放就好了。 (多边形旋转其实是绕给出的第一个点旋转,以为是绕原点wa了1发)。

    AC代码

      1 #include <bits/stdc++.h>
      2 #define Vector Point
      3 using namespace std;
      4 typedef long long ll;
      5 const double eps = 1e-9;
      6 const double PI=acos(-1);
      7 const int maxn = 1e5+10,inf=0x3f3f3f3f;
      8 //head-------------------------------------------------------------------
      9 int dcmp(double x) { return fabs(x) < eps ? 0 : (x < 0 ? -1 : 1); }
     10 struct Point {
     11     double x, y;
     12 
     13     Point(const Point& rhs): x(rhs.x), y(rhs.y) { } //拷贝构造函数
     14     Point(double x = 0.0, double y = 0.0): x(x), y(y) { }   //构造函数
     15 
     16     friend istream& operator >> (istream& in, Point& P) { return in >> P.x >> P.y; }
     17     friend ostream& operator << (ostream& out, const Point& P) { return out << P.x << ' ' << P.y; }
     18 
     19     friend Vector operator + (const Vector& A, const Vector& B) { return Vector(A.x+B.x, A.y+B.y); }
     20     friend Vector operator - (const Point& A, const Point& B) { return Vector(A.x-B.x, A.y-B.y); }
     21     friend Vector operator * (const Vector& A, const double& p) { return Vector(A.x*p, A.y*p); }
     22     friend Vector operator / (const Vector& A, const double& p) { return Vector(A.x/p, A.y/p); }
     23     friend bool operator == (const Point& A, const Point& B) { return dcmp(A.x-B.x) == 0 && dcmp(A.y-B.y) == 0; }
     24     friend bool operator < (const Point& A, const Point& B) { return dcmp(A.x - B.x)<0 || (dcmp(A.x - B.x)==0 && dcmp(A.y - B.y)<0); }
     25     void in() { scanf("%lf%lf", &x, &y); }
     26     void out() { printf("%.10f %.10f
    ", x, y); }
     27 };
     28 
     29 template <class T> T sqr(T x) { return x * x;}
     30 double Dot(const Vector& A, const Vector& B) { return A.x*B.x + A.y*B.y; }  //点积
     31 double Length(const Vector& A){ return sqrt(Dot(A, A)); } //向量长度
     32 double Angle(const Vector& A, const Vector& B) { return acos(Dot(A, B)/Length(A)/Length(B)); }  //AB向量夹角
     33 double Cross(const Vector& A, const Vector& B) { return A.x*B.y - A.y*B.x; }    //AB叉积 有向面积
     34 double Area(const Point& A, const Point& B, const Point& C) { return fabs(Cross(B-A, C-A)); }
     35 //向量旋转 rad正表示逆时针 反之顺时针
     36 Vector Rotate(Vector A,double rad){ return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}
     37 //A不能是0向量
     38 Vector normal(Vector A) { return Point(-A.y, A.x) / Length(A);} //向量A的单位法向量,即A左转90度 以后把长度归归一化
     39 double angle(Vector A) { return atan2(A.y, A.x);} //向量极角 向量A与x轴的夹角
     40 Vector vecunit(Vector A){ return A / Length(A);} //单位向量
     41 
     42 struct Line {
     43     Point P;    //直线上一点
     44     Vector dir; //方向向量(半平面交中该向量左侧表示相应的半平面)
     45     double ang; //极角,即从x正半轴旋转到向量dir所需要的角(弧度)
     46 
     47     Line() { }  //构造函数
     48     Line(const Line& L): P(L.P), dir(L.dir), ang(L.ang) { }
     49     Line(const Point& P, const Vector& dir): P(P), dir(dir) { ang = atan2(dir.y, dir.x); }
     50 
     51     bool operator < (const Line& L) const { //极角排序
     52         return ang < L.ang;
     53     }
     54     Point point(double t) { return P + dir*t; }
     55 };
     56 
     57 
     58 //直线交点1 P+tv Q+tw
     59 Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)
     60 {
     61     Vector u=P-Q;
     62     double t = Cross(w,u)/Cross(v,w);
     63     return P+v*t;
     64 }
     65 //直线交点2
     66 Point GetIntersection(Line a, Line b)
     67 {
     68     Vector u = a.P-b.P;
     69     double t = Cross(b.dir, u) / Cross(a.dir, b.dir);
     70     return a.P + a.dir*t;
     71 }
     72 bool SegmentProperInntersection(Point a1,Point a2,Point b1,Point b2)//线段相交判定
     73 {
     74     double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),
     75            c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
     76     return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
     77 }
     78 double DistanceToSegment(Point P,Point A,Point B) //点P到线段AB的距离
     79 {
     80     if(A==B) return Length(P-A);
     81     Vector v1 = B - A,v2 = P - A,v3 = P - B;
     82     if(dcmp(Dot(v1,v2))<0) return Length(v2);
     83     else if(dcmp(Dot(v1,v3))>0) return Length(v3);
     84     else return fabs(Cross(v1,v2))/Length(v1);
     85 }
     86 Point GetLineProjection(Point P,Point A,Point B) //点P在直线AB上的投影
     87 {
     88     Vector v = B-A;
     89     return A+v*(Dot(v,P-A)/Dot(v,v));
     90 }
     91 bool OnSegment(Point p, Point a1, Point a2) //判断点是否在线段a1a2上 不含端点
     92 {
     93     return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
     94 }
     95 
     96 struct Circle {
     97     Point c;    //圆心
     98     double r;   //半径
     99 
    100     Circle() { }
    101     Circle(const Circle& rhs): c(rhs.c), r(rhs.r) { }
    102     Circle(const Point& c, const double& r): c(c), r(r) { }
    103 
    104     Point point(double ang) const { return Point(c.x + cos(ang)*r, c.y + sin(ang)*r); } //圆心角所对应的点
    105     double area(void) const { return PI * r * r; }
    106 };
    107 bool InCircle(Point x, Circle c)
    108 {
    109     return dcmp(c.r*c.r - Length(c.c - x)*Length(c.c - x)) >= 0;
    110 }
    111 //直线与圆的交点
    112 int getLineCircleIntersection(Line L, Circle C, Point* sol) //函数返回交点个数 sol数组存放交点
    113 {
    114     Vector nor = normal(L.dir);
    115     Line pl = Line(C.c, nor);
    116     Point ip = GetIntersection(pl, L);
    117     double dis = Length(ip - C.c);
    118     if (dcmp(dis - C.r) > 0) return 0;
    119     Point dxy = vecunit(L.dir) * sqrt(C.r*C.r - dis*dis);
    120     int ret = 0;
    121     sol[ret] = ip + dxy;
    122     if (OnSegment(sol[ret], L. P, L.point(1))) ret++;
    123     sol[ret] = ip - dxy;
    124     if (OnSegment(sol[ret], L.P, L.point(1))) ret++;
    125     return ret;
    126 }
    127 //圆与圆的交点
    128 int getCircleCircleIntersection(Circle C1,Circle C2,vector<Point>& sol)//函数返回交点个数 sol数组存放交点
    129 {
    130     double d=Length(C1.c-C2.c);
    131     if(dcmp(d)==0){
    132         if(dcmp(C1.r-C2.r)==0) return -1;//两圆重合
    133         return 0;
    134     }
    135     if(dcmp(C1.r+C2.r-d)<0) return 0;
    136     if(dcmp(fabs(C1.r-C2.r)-d)>0) return 0;
    137 
    138     double a=angle(C2.c-C1.c);
    139     double da=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));
    140     Point p1=C1.point(a-da),p2=C1.point(a+da);
    141     sol.push_back(p1);
    142     if(p1==p2) return 1;
    143     sol.push_back(p2);
    144     return 2;
    145 }
    146 //过点p到圆c的切线
    147 int getTangents(Point p,Circle C,Vector* v)//函数返回条数,v[i]是第i条切线的向量
    148 {
    149     Vector u=C.c-p;
    150     double dist=Length(u);
    151     if(dist<C.r) return 0;  //点在圆内
    152     else if(dcmp(dist-C.r)==0){//p在圆c上,只有一条切线
    153         v[0]=Rotate(u,PI/2);
    154         return 1;
    155     }else{
    156         double ang = asin(C.r/dist);
    157         v[0]=Rotate(u,-ang);
    158         v[1]=Rotate(u,ang);
    159         return 2;
    160     }
    161 }
    162 //两圆的公切线
    163 int getTangents(Circle A,Circle B,Point* a,Point* b)
    164 {
    165     int cnt=0;
    166     if(A.r<B.r){swap(A,B);swap(a,b);}
    167     double d2=(A.c.x-B.c.x)*(A.c.x-B.c.x)+(A.c.y-B.c.y)*(A.c.y-B.c.y);
    168     double rdiff=A.r - B.r;
    169     double rsum=A.r + B.r;
    170     if(d2<rdiff*rdiff) return 0;//内含
    171 
    172     double base = atan2(B.c.y-A.c.y,B.c.x-A.c.x);
    173     if(dcmp(d2)==0&&dcmp(A.r-B.r)==0) return -1;//两圆重合,无数条切线
    174     if(dcmp(d2-rdiff*rdiff)==0){                 //内切,1条切线
    175         a[cnt]=A.point(base);b[cnt]=B.point(base);cnt++;
    176         return 1;
    177     }
    178     //有外公切线
    179     double ang=acos((A.r-B.r)/sqrt(d2));
    180     a[cnt] = A.point(base+ang);b[cnt] = B.point(base+ang);cnt++;
    181     a[cnt] = A.point(base-ang);b[cnt] = B.point(base-ang);cnt++;
    182     if(dcmp(d2-rsum*rsum)==0){       //一条内公切线
    183         a[cnt]=b[cnt]=A.point(base);cnt++;
    184     }
    185     else if(dcmp(d2-rsum*rsum)>0){   //两条内公切线
    186         ang = acos((A.r+B.r)/sqrt(d2));
    187         a[cnt] = A.point(base+ang);b[cnt] = B.point(PI+base+ang);cnt++;
    188         a[cnt] = A.point(base-ang);b[cnt] = B.point(PI+base-ang);cnt++;
    189     }
    190     return cnt;
    191 }
    192 double SegCircleArea(Circle C, Point a, Point b) //线段切割圆
    193 {
    194     double a1 = angle(a - C.c);
    195     double a2 = angle(b - C.c);
    196     double da = fabs(a1 - a2);
    197     if (da > PI) da = PI * 2.0 - da;
    198     return dcmp(Cross(b - C.c, a - C.c)) * da * sqr(C.r) / 2.0;
    199 }
    200 
    201 double PolyCiclrArea(Circle C, Point *p, int n)//多边形与圆相交面积
    202 {
    203     double ret = 0.0;
    204     Point sol[2];
    205     p[n] = p[0];
    206     for(int i=0;i<n;i++)
    207     {
    208         double t1, t2;
    209         int cnt = getLineCircleIntersection(Line(p[i], p[i+1]-p[i]), C, sol);
    210         if (cnt == 0)
    211         {
    212             if (!InCircle(p[i], C) || !InCircle(p[i+1], C)) ret += SegCircleArea(C, p[i], p[i+1]);
    213             else ret += Cross(p[i+1] - C.c, p[i] - C.c) / 2.0;
    214         }
    215         if (cnt == 1)
    216         {
    217             if (InCircle(p[i], C) && !InCircle(p[i+1], C)) ret += Cross(sol[0] - C.c, p[i] - C.c) / 2.0, ret += SegCircleArea(C, sol[0], p[i+1]);
    218             else ret += SegCircleArea(C, p[i], sol[0]), ret += Cross(p[i+1] - C.c, sol[0] - C.c) / 2.0;
    219         }
    220         if (cnt == 2)
    221         {
    222             if ((p[i] < p[i + 1]) ^ (sol[0] < sol[1])) swap(sol[0], sol[1]);
    223             ret += SegCircleArea(C, p[i], sol[0]);
    224             ret += Cross(sol[1] - C.c, sol[0] - C.c) / 2.0;
    225             ret += SegCircleArea(C, sol[1], p[i+1]);
    226         }
    227     }
    228     return fabs(ret);
    229 }
    230 double PolygonArea(Point *po, int n) //多边形面积
    231 {
    232     double area = 0.0;
    233     for(int i = 1; i < n-1; i++) {
    234         area += Cross(po[i]-po[0], po[i+1]-po[0]);
    235     }
    236     return area * 0.5;
    237 }
    238 //-----------------------------------------------------------------------------------
    239 Point p[maxn];
    240 int main()
    241 {
    242     double a,w,h;
    243     int n;
    244     cin>>a>>w>>h>>n;
    245     double ang=a/180*PI;
    246     double minx=inf,maxx=-1.0;
    247     double miny=inf,maxy=-1.0;
    248     for(int i=0;i<n;i++)
    249     {
    250         p[i].in();
    251         p[i]=p[0]+Rotate(p[i]-p[0],ang);
    252         minx=min(minx,p[i].x);
    253         miny=min(miny,p[i].y);
    254         maxx=max(maxx,p[i].x);
    255         maxy=max(maxy,p[i].y);
    256     }
    257     double dux=w/(maxx-minx);
    258     double duy=h/(maxy-miny);
    259     for(int i=0;i<n;i++)
    260     {
    261         p[i].x-=minx;
    262         p[i].y-=miny;
    263         p[i].x*=dux;
    264         p[i].y*=duy;
    265         p[i].out();
    266     }
    267 }
    View Code

    题意:给出n个狗的坐标,m个碗的坐标和碗里的数的数量w L(升) , 狗每一秒可以走一个单位长度,狗喝水需要10s ,问S秒内每只狗从自己的位置出发是否全部都能喝完1L水。

    题解:如果距离在时限内狗和碗连边,碗拆点就可以了。源点汇点不说了,很简单。

    AC代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1e4+20,mod=1e9+7,inf=0x3f3f3f3f;
      4 typedef long long ll;
      5 struct edge
      6 {
      7     int from,to,c,f;
      8     edge(int u,int v,int c,int f):from(u),to(v),c(c),f(f) {}
      9 };
     10 int n,m;
     11 vector<edge> edges;
     12 vector<int> g[maxn];
     13 int d[maxn];//从起点到i的距离
     14 int cur[maxn];//当前弧下标
     15 void init(int N)
     16 {
     17     for(int i=0; i<=N; i++) g[i].clear();
     18     edges.clear();
     19 }
     20 void addedge(int from,int to,int c) //加边 支持重边
     21 {
     22     edges.push_back(edge(from,to,c,0));
     23     edges.push_back(edge(to,from,0,0));
     24     int siz=edges.size();
     25     g[from].push_back(siz-2);
     26     g[to].push_back(siz-1);
     27 }
     28 int bfs(int s,int t) //构造一次层次图
     29 {
     30     memset(d,-1,sizeof(d));
     31     queue<int> q;
     32     q.push(s);
     33     d[s]=0;
     34     while(!q.empty())
     35     {
     36         int x=q.front();q.pop();
     37         for(int i=0;i<g[x].size();i++)
     38         {
     39             edge &e=edges[g[x][i]];
     40             if(d[e.to]<0&&e.f<e.c) //d[e.to]=-1表示没访问过
     41             {
     42                 d[e.to]=d[x]+1;
     43                 q.push(e.to);
     44             }
     45         }
     46     }
     47     return d[t];
     48 }
     49 int dfs(int x,int a,int t) // a表示x点能接收的量
     50 {
     51     if(x==t||a==0)return a;
     52     int flow=0,f;//flow总的增量 f一条增广路的增量
     53     for(int &i=cur[x];i<g[x].size();i++)//cur[i] &引用修改其值 从上次考虑的弧
     54     {
     55         edge &e=edges[g[x][i]];
     56         if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.c-e.f),t))>0)    //按照层次图增广 满足容量限制
     57         {
     58             e.f+=f;
     59             edges[g[x][i]^1].f-=f;  //修改流量
     60             flow+=f;
     61             a-=f;
     62             if(a==0) break;
     63         }
     64     }
     65     return flow;
     66 }
     67 int maxflow(int s,int t)
     68 {
     69     int flow=0;
     70     while(bfs(s,t)!=-1) //等于-1代表构造层次图失败 结束
     71     {
     72         memset(cur,0,sizeof(cur));
     73         flow+=dfs(s,inf,t);
     74     }
     75     return flow;
     76 }
     77 struct node
     78 {
     79     ll first,second;
     80 }dog[maxn],bowl[maxn];
     81 int num[maxn];
     82 ll s;
     83 int main()
     84 {
     85     while(scanf("%d%d%lld",&n,&m,&s)!=EOF)
     86     {
     87         init(n+2*m+1);
     88         for(int i=1;i<=n;i++)
     89             scanf("%lld%lld",&dog[i].first,&dog[i].second);
     90         for(int i=1;i<=m;i++)
     91             scanf("%lld%lld%d",&bowl[i].first,&bowl[i].second,&num[i]);
     92         for(int i=1;i<=n;i++)
     93         {
     94             addedge(0,i,1);
     95             for(int j=1;j<=m;j++)
     96             {
     97                 if(sqrt(pow(abs(dog[i].first-bowl[j].first),2)+pow(abs(dog[i].second-bowl[j].second),2))+10<=s)
     98                     addedge(i,n+j,1);
     99             }
    100         }
    101         for(int j=1;j<=m;j++)
    102             addedge(n+j,n+m+j,num[j]),
    103             addedge(n+m+j,n+2*m+1,inf);
    104         if(maxflow(0,n+m*2+1)==n)
    105             printf("YES
    ");
    106         else
    107             printf("NO
    ");
    108     }
    109 }
  • 相关阅读:
    Vmware14中设置Centos7静态密码
    字符串和集合截取
    通过FTP连上centos7
    centos7 离线安装mysql-5.7.21
    基于jackson注释@JsonFormat 格式化时间少8小时
    Kotlin基础学习笔记 (三)
    Android 常用开源框架源码解析 系列 (零)引言
    Kotlin基础学习笔记 (一)
    Android 常用开源框架源码解析 系列 (十一)picasso 图片框架
    Android 常用开源框架源码解析 系列 (十)Rxjava 异步框架
  • 原文地址:https://www.cnblogs.com/stranger-/p/10840551.html
Copyright © 2020-2023  润新知