zoukankan      html  css  js  c++  java
  • 2020-07-05 热身训练赛(五)

    A.(Gym-12483A)

    B.(Gym-12483B)

    C.构造图(Gym-12483C)

    题意:给出一个树,要求写出每个节点的坐标,使得相邻节点之间的距离为1,并且任何一对节点之间的距离最少为$10^{-4}$,相邻节点之间的距离与1的绝对误差最多为$10^{-6}$,不连接在同一节点的边之间的距离至少为$10^{-6}$,坐标的绝对值不超过$3000$。

    解:分配边转化为分配角度$ heta$,那么点的坐标就是$(x+cos heta,y+sin heta)$,为了避免交叉,利用树的结构进行dfs,角度按照dfs的顺序增大,这样就可以保证边不重叠了,实际上不用刻意的研究$10^{-4}和10^{-6}$,可以认为这两个数字就表示无穷小,也就是点重叠,边交叉的情况。比赛的时候没认真考虑边交叉,就用了bfs,后来队友也写了一个,写的dfs,但也wa了。赛后去看了一下别人的代码,才突然意识到这个问题。队友写的dfs我也看了一下,发现里面出了一个极小无比的错误,改掉就过了。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define maxn 1001
    #ifndef M_PI
    #define M_PI 3.14159265358979323846
    #endif
    using namespace std;
    int num,head[maxn];
    struct node{
        int to,pre;
    }e[maxn*2];
    
    void Insert(int from,int to){
        e[++num].to=to;
        e[num].pre=head[from];
        head[from]=num;
    }
    
    struct point{
        double x,y;
    }p[maxn];
    
    int n;
    double Eps;
    bool vis[maxn];
    
    int cnt=-1;
    void dfs(int now){
        for(int i=head[now];i;i=e[i].pre){
            int to=e[i].to;
            if(!vis[to]){
                vis[to]=1;
                cnt++;
                p[to].x=p[now].x+cos(Eps*cnt);
                p[to].y=p[now].y+sin(Eps*cnt);
                dfs(to);
            }
        }
    }
    int main(){
        scanf("%d",&n);
        Eps=(double)M_PI/(double)1000;
        int x,y;
        for(int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            Insert(x,y);Insert(y,x);
        }
        p[1].x=0;p[1].y=0;
        vis[1]=1;
        dfs(1);
        for(int i=1;i<=n;i++){
            printf("%.15f %.15f
    ",(double)p[i].x,(double)p[i].y);
        }
        return 0;
    }

    D.(Gym-12483D)

    E.(Gym-12483E)

    F.(Gym-12483F)

    G.构造障碍(Gym-12483G)

    题意:在一个平面上有一个小球,许多障碍物和一个洞(洞的坐标为(0,0)),将平板向一个方向倾斜,就可以使小球向这个方一直滚动,直到遇到障碍物或者进洞。题目给出一个包含LRUD的字符串,表示平板倾斜的方向序列,要求根据这个序列设计一种障碍物的摆放方法,使小球最后能顺利进洞,不能满足条件的输出impossible。

    解:规定小球从(0,0)开始滚动,最后根据最终的位置应该在(0,0),把所有的点进行平移。可以先判断能够产生impossible的情况,impossible实际上就是中途进洞,因为最后一步移动要把小球移动到洞里,所以如果有LRL,RLR,UDU,DUD这四种情况出现在最后三次操作中,就直接输出impossible了。求路径时,如果有RLRL这类情况,就可以只设置左右两个障碍,如果出现RU这类情况,就把小球向U移两格,设置新的障碍。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define maxn 10010
    using namespace std;
    char s[21];
    int n,cnt;
    bool flag;
    struct node{
        int x,y;
        bool operator == (const node u)const{
            if(x==u.x&&y==u.y)return 1;
            return 0;
        }
        bool operator < (const node u)const{
            if(x!=u.x)return x<u.x;
            return y<u.y;
        } 
    }ans[maxn];
    int main(){
        scanf("%s",s+1);
        n=strlen(s+1);
        if(n>=3){
            if(!strcmp(s+n-2,"LRL"))flag=1;
            if(!strcmp(s+n-2,"RLR"))flag=1;
            if(!strcmp(s+n-2,"UDU"))flag=1;
            if(!strcmp(s+n-2,"DUD"))flag=1;
        }
        if(flag){
            puts("impossible");
            return 0;
        }
        int d=1;
        int x=0,y=0;
        for(int i=1;i<=n;i++){
            if(s[i]=='R'){
                x=d;
                ans[++cnt]={x+1,y};
            }
            if(s[i]=='L'){
                x=-d;
                ans[++cnt]={x-1,y};
            }
            if(s[i]=='U'){
                y=d;
                ans[++cnt]={x,y+1};
            }
            if(s[i]=='D'){
                y=-d;
                ans[++cnt]={x,y-1};
            }
            if(i+1<=n){
                if(s[i]=='L'&&s[i+1]=='R');
                else if(s[i]=='R'&&s[i+1]=='L');
                else if(s[i]=='U'&&s[i+1]=='D');
                else if(s[i]=='D'&&s[i+1]=='U');
                else d+=2;
            }
        }
        printf("%d %d
    ",-x,-y);
        sort(ans+1,ans+cnt+1);
        n=unique(ans+1,ans+cnt+1)-ans-1;
        printf("%d
    ",n);
        for(int i=1;i<=n;i++){
            printf("%d %d
    ",ans[i].x-x,ans[i].y-y);
        }
        return 0;
    }

    H.(Gym-12483H)

    题意:一共有n个位置,可以填入0或1,如果相邻两个数字不同,就称为有一个change,题目中指定b个位置只能为0(约定第一个位置不指定,最后一个位置指定),其它位置填0或者1,使得恰好有c个change,要求写出一种符合要求的01串。

    解:可以发现如果在两个0之间填1,无论如何都会增加偶数个change,而如果在第一个位置填了1,那么无论如何都会增加奇数个1。所以可以通过c的奇偶性来判断第一个位置应该填的数。然后根据剩下的需要满足的change数,来顺次填不一样的数字。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 500010
    using namespace std;
    int n,c,b,a[maxn];
    int main(){
        scanf("%d%d%d",&n,&c,&b);
        memset(a,-1,sizeof(a));
        int x;
        for(int i=1;i<=b;i++){
            scanf("%d",&x);
            a[x]=0;
        }
        if(c%2==1){a[1]=1;}
        else a[1]=0;
        for(int i=2;i<=n;i++){
            if(a[i]==-1){
                if(c>0)a[i]=!a[i-1];
            }
            if(a[i]!=a[i-1])c--;
            if(c<=0)break;
        }
        for(int i=1;i<=n;i++){
            if(a[i]==-1)a[i]=0;
            printf("%d",a[i]);
        }
        puts("");
        return 0;
    }

    I.(Gym-12483I)

    J.(Gym-12483J)

    K.(Gym-12483K)

  • 相关阅读:
    poj 1850/poj 1496
    poj 1035
    poj 3252
    hdoj 1013
    poj 2965
    poj 1844
    poj 2309
    蓝桥杯比赛回来后计划。。。
    山大实训第二周感想
    hadoop——Map/Reduce中combiner的使用
  • 原文地址:https://www.cnblogs.com/thmyl/p/13251854.html
Copyright © 2011-2022 走看看