2018 BUPT Winter Training #6 Div.2

12 篇文章 0 订阅
3 篇文章 0 订阅

A - Intersecting Lines

rt,求相交直线。

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
using namespace std;
const double eps = 1e-6;
struct Point {
    double x,y;
    Point(){}
    Point(double _x,double _y){x = _x;y = _y;}
    Point get(){cin>>x>>y;return Point(x,y);}
    Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
    Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
    double operator*(const Point &b)const{return x*b.x+y*b.y;}
    double operator^(const Point &b)const {return x*b.y-y*b.x;}
}P[5];
int main(void) {
    int T,t;
    cin>>T;
    cout<<"INTERSECTING LINES OUTPUT\n";
    while(T--){
        FF(i,1,4)P[i].get();
        if(fabs((P[2]-P[1])^(P[4]-P[3]))<eps){
            if(fabs((P[3]-P[1])^(P[4]-P[1]))<eps)cout<<"LINE"<<endl;
            else cout<<"NONE"<<endl;
        }else{
            double a1=P[1].y-P[2].y,a2=P[3].y-P[4].y;
            double b1=P[2].x-P[1].x,b2=P[4].x-P[3].x;
            double c1=P[1]^P[2],c2=P[3]^P[4];
            double D=a1*b2-a2*b1;
            cout<<fixed<<"POINT "<<setprecision(2)<<(b1*c2-b2*c1)/D<<" "<<(a2*c1-a1*c2)/D<<endl;
        }
    }
    cout<<"END OF OUTPUT\n";
}

B - The Doors

暴力枚举线段相交…这就很不优美了。

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <utility>
#include <queue>
#include <iomanip>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define PB push_back
#define all(x) x.begin(),x.end()
#define MP make_pair
#define sec second
#define fir first
using namespace std;

const double eps=1e-7;
int sgn(double x){
    return (fabs(x)>=eps)*x;
}
struct Point {
    double x,y;
    Point(){}
    Point(double _x,double _y){x=_x;y=_y;}
    Point get(){cin>>x>>y;return Point(x,y);}
    Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
    Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
    double operator*(const Point &b)const{return x*b.x+y*b.y;}
    double operator^(const Point &b)const {return x*b.y-y*b.x;}
};
struct Line {
    Point a,b;
    Line(){}
    Line(Point _a,Point _b){a=_a;b=_b;}
};
typedef pair<double,Line> W;
vector<int> ade[150];
vector<W> wall;
vector<Point> P;
inline double dis(int x,int y){return sqrt((P[x].x-P[y].x)*(P[x].x-P[y].x)+(P[x].y-P[y].y)*(P[x].y-P[y].y));}
inline bool SegCross(Line a,Line b){
    return ((a.a-b.a)^(a.b-b.a))*((a.a-b.b)^(a.b-b.b))<0&&((b.a-a.a)^(b.b-a.a))*((b.a-a.b)^(b.b-a.b))<0;
}
bool check(int x,int y){
    Line l=Line(P[x],P[y]);
    double m;
    TRV(w,wall){
        if(P[x].x<=wall[w].fir&&wall[w].fir<=P[y].x&&SegCross(l,wall[w].sec))return 0;
    }
    return 1;
}
typedef pair<double,int> pdi; 
bool vis[120];
int main(){
    pdi t;int n,e;double x,y1,y2,y3,y4;Point start=Point(0,5),end=Point(10,5);
    ios::sync_with_stdio(false);
    while(cin>>n&&n!=-1){
        P.clear();wall.clear();
        F(i,(n<<2)+10)ade[i].clear();
        memset(vis,0,sizeof(vis));
        priority_queue<pdi,vector<pdi>,greater<pdi> > q;

        P.PB(start);
        F(i,n){
            cin>>x>>y1>>y2>>y3>>y4;
            P.PB(Point(x,y1));
            P.PB(Point(x,y2));
            P.PB(Point(x,y3));
            P.PB(Point(x,y4));
            e=(i<<2)+1;
            wall.PB(MP(x,Line(Point(x,0),P[e])));
            wall.PB(MP(x,Line(P[e+1],P[e+2])));
            wall.PB(MP(x,Line(P[e+3],Point(x,10))));
        }
        e=P.size();
        P.PB(end);
        TRV(i,P)F(j,i)if(check(j,i))ade[j].PB(i);
        q.push(MP(0,0));
        while(!q.empty()){
            t=q.top();q.pop();
            if(vis[t.sec])continue;
            vis[t.sec]=1;
            if(t.sec==e)break;
            TRV(i,ade[t.sec])q.push(MP(t.fir+dis(t.sec,ade[t.sec][i]),ade[t.sec][i]));
        }
        cout<<fixed<<setprecision(2)<<t.fir<<endl;
    }
}

C - Space Ant

求连接点最多的螺旋线,用极角排序就ok了。

#include <iostream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iomanip>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
const double eps=1e-8;
inline double sgn(double x){return (fabs(x)>=eps)*x;}
struct Point {
    double x,y;
    int id;
    Point(){}
    Point(double _x,double _y,int _id=0){id=_id;x = _x;y = _y;}
    Point get(){cin>>id>>x>>y;return Point(x,y,id);}
    bool operator<(const Point &b)const{return y<b.y||(y==b.y&&x<b.x);}
    Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
    Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
    double operator*(const Point &b)const{return x*b.x+y*b.y;}
    double operator^(const Point &b)const {return x*b.y-y*b.x;}
}P[105];
//inline double dis(int x,int y){return sqrt((P[x]-P[y])*(P[x]-P[y]));}
//inline double dis(int x,int y){return (P[x]-P[y])*(P[x]-P[y]);}
//inline double dis(Point x,Point y){return sqrt((x-y)*(x-y));}
inline double dis(Point x,Point y){return (x-y)*(x-y);}
int cur;
bool cmp(Point x,Point y){
    double t=sgn((x-P[cur])^(y-P[cur]));
    return t==0&&dis(x,P[cur])<dis(y,P[cur])||t>0;
}
int main(){
    int T,n;
    ios::sync_with_stdio(false);
    P[0]=Point(0,0);
    for(cin>>T;T--;){
        cin>>n;
        FF(i,1,n){
            P[i].get();
            if(P[i]<P[1])swap(P[1],P[i]);
        }
        cur=1;
        cout<<n<<" "<<P[1].id;
        FF(i,2,n){sort(P+i,P+n+1,cmp);cout<<" "<<P[cur=i].id;}
        cout<<endl;
    }
}

D…阵亡

E - Grandpa’s Estate

因为已经是个凸包了,所以不需要判凸包。极角排序后判断同一个边上是否至少有三个点即可。坑爹的是,这道题我WA6次,原因是”YES”“NO”写成了”Yes”“No”…真是破坏了我补div2#6的心情…所以我才没怎么补这次比赛的题了..有时间再把没过的题好好过一遍吧。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
const double eps=1e-7;
double sgn(double x){
    return (fabs(x)>=eps)*x;
}
struct Point {
    double x,y;
    Point(){}
    Point(double _x,double _y){x = _x;y = _y;}
    Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
    Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
    double operator*(const Point &b)const{return x*b.x+y*b.y;}
    double operator^(const Point &b)const {return x*b.y-y*b.x;}
    bool operator==(const Point &b)const{return x==b.x&&y==b.y;}
}P[1005],X;
inline double dis(Point x,Point y){return sqrt((x-y)*(x-y));}
bool cmp(Point x,Point y){
    double f=(x-X)^(y-X);
    if(f>0)return 1;
    if(f==0&&dis(x,X)<dis(y,X))return 1;
    return 0;
}
bool Judge(int n){
    int curr=0;
    bool FIND=0,JUDGE=0;
    Point Vec,pre;
    for(;;){
        if(curr==n)return 1;
        Vec=P[curr+1]-P[curr];
        if(FIND&&(pre^Vec)==0){
            pre=Vec;curr++;continue;
        }else FIND=0;
        if(JUDGE)if((pre^Vec)!=0)return 0;else FIND=1,JUDGE=0;
        else JUDGE=1;
        pre=Vec;curr++;
    }
}
int main(){
    int T,n;
    for(scanf("%d",&T);T--;){
        scanf("%d",&n);
        memset(P,0,sizeof(P));
        F(i,n){
            scanf("%lf%lf",&P[i].x,&P[i].y);
            if(P[i].y<P[0].y||P[i].y==P[0].y&&P[i].x<P[0].x)swap(P[0],P[i]);
        }
        X=P[0];
        sort(P,P+n,cmp);
        P[n]=P[0];
        if(n<6){puts("NO");continue;}
        if(((P[n]-P[n-1])^(P[n-1]-P[n-2]))!=0){puts("NO");continue;}
        X=P[n-1];
        while(((P[n]-P[n-1])^(P[n-1]-P[n-2]))==0)n--;
        n--;P[n]=X;
        puts(Judge(n)?"YES":"NO");
    }
}

F..先算了

G - Circle and Points

3200ms:思路是枚举所有可能的圆。
1400ms:因为单位圆的半径是1,判断不需要sqrt,这样效率就大幅升高了。
1200ms:增加离散化评价,如果求得圆心周围九个格子的点还不如ans,就不需要判断了。

//3200ms
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define eps 1e-8
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
struct Point {
    double x,y;
    Point(){}
    Point(double _x,double _y){x = _x;y = _y;}
    Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
    Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
    Point operator/(const double k)const{return Point(x/k,y/k);}
    double operator*(const Point &b)const{return x*b.x+y*b.y;}
    double operator^(const Point &b)const {return x*b.y-y*b.x;}
    bool operator==(const Point &b)const{return x==b.x&&y==b.y;}
    bool operator<(const Point &b)const{return x<b.x||x==b.x&&y<b.y;}
}P[305];
inline double dis(Point x,Point y){return sqrt((x-y)*(x-y));}
//1400ms:用下面dis2函数代替dis判断
//inline double dis2(Point x,Point y){return (x-y)*(x-y);}
void getmid(Point P1,Point P2,Point &center) {
    Point mid;
    mid.x=(P1.x+P2.x)/2.0;
    mid.y=(P1.y+P2.y)/2.0;
    double angle=atan2(P1.x-P2.x,P2.y-P1.y);
    double dcm=sqrt(1-dis(P1,mid)*dis(P1,mid));
    center.x=mid.x+dcm*cos(angle);
    center.y=mid.y+dcm*sin(angle);
}
int main() {
    int n,i,j,k;
    while(scanf("%d",&n),n){
        F(i,n)scanf("%lf%lf",&P[i].x,&P[i].y);
        int ans=1;
        F(i,n){
            for(j=i+1; j<n; ++j) {
                if(dis(P[i],P[j])>2.0)continue;
                Point center;
                getmid(P[i],P[j],center);
                int cnt=0;
                F(k,n){
                    if(fabs(P[k].x-center.x)>1||fabs(P[k].y-center.y)>1)continue;
                    if(dis(P[k],center)<1.0+eps)cnt++;
                }
                if(ans<cnt)ans=cnt;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
//1200ms
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include <map>
#include<algorithm>
#define eps 1e-8
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
struct Point {
    double x,y;
    Point(){}
    Point(double _x,double _y){x = _x;y = _y;}
    Point operator+(const Point &b)const{return Point(x+b.x,y+b.y);}
    Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}
    Point operator/(const double k)const{return Point(x/k,y/k);}
    double operator*(const Point &b)const{return x*b.x+y*b.y;}
    double operator^(const Point &b)const {return x*b.y-y*b.x;}
    bool operator==(const Point &b)const{return x==b.x&&y==b.y;}
    bool operator<(const Point &b)const{return x<b.x||x==b.x&&y<b.y;}
}A[305];
int conj[12][12];
inline double dis(Point x,Point y){return sqrt((x-y)*(x-y));}
inline double dis2(Point x,Point y){return (x-y)*(x-y);}
void getmid(Point P1,Point P2,Point &center) {
    Point mid;
    mid.x=(P1.x+P2.x)/2.0;
    mid.y=(P1.y+P2.y)/2.0;
    double angle=atan2(P1.x-P2.x,P2.y-P1.y);
    double dcm=sqrt(1-dis(P1,mid)*dis(P1,mid));
    center.x=mid.x+dcm*cos(angle);
    center.y=mid.y+dcm*sin(angle);
}
int main() {
    int n,i,j,k,ttt;
    while(scanf("%d",&n),n){
        memset(conj,0,sizeof(conj));
        F(i,n){
            scanf("%lf%lf",&A[i].x,&A[i].y);
            conj[(int)A[i].x+1][(int)A[i].y+1]++;
        }
        int ans=1,x,y;
        F(i,n){
            for(j=i+1; j<n; ++j) {
                if(dis(A[i],A[j])>2.0)continue;
                Point center;
                getmid(A[i],A[j],center);
                x=(int)(center.x);y=(int)(center.y);
                if(conj[x+1][y+1]+conj[x][y]+conj[x][y+1]+conj[x][y+2]+conj[x+1][y]+conj[x+1][y+2]+conj[x+2][y]+conj[x+2][y+1]+conj[x+2][y+2]<ans)continue;
                int cnt=0;
                F(k,n){
                    if(dis2(A[k],center)<1.0+eps)cnt++;
                }
                if(ans<cnt)ans=cnt;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

H题。。。看pdf蛋疼,先不补了。

I - Disks

那些对向右扩展没有贡献的圆就是答案了。

#include <cstdio>
#include <cmath>
#include <cstring>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
double R[1005],Local[1005];
int anss[1005],adj[1005]={0};
int main(){
    memset(adj,-1,sizeof(adj));
    int n,ans=0,ar=0;double r=0,dis,r2,r1;
    Local[0]=R[0]=0;
    scanf("%d",&n);
    FF(i,1,n)scanf("%lf",&R[i]);
    FF(i,1,n){
        Local[i]=R[i];
        FF(j,1,i-1){
            r1=R[j];r2=R[i];if(r1<r2)r1=R[i],r2=R[j];
            dis=sqrt((r1+r2)*(r1+r2)-(r1-r2)*(r1-r2))+Local[j];
            if(Local[i]<dis){
                Local[i]=dis;
                adj[i]=j;
            }
        }
        if(r<Local[i]+R[i])r=Local[ar=i]+R[i];
    }
    for(int i=n;i>ar;i--)anss[ans++]=i;
    for(int i=ar;i>0;i=adj[i]){
        ar=i-1;
        while(ar>0&&ar>adj[i])anss[ans++]=ar--;
    }
    printf("%d\n",ans);
    for(int i=ans-1;i+1;i--)printf("%d\n",anss[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值