2020-07-05 热身训练赛(五)

A.(Gym-12483A)

 

B.(Gym-12483B)

C.构造图(Gym-12483C)

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

解:分配边转化为分配角度$\theta$,那么点的坐标就是$(x+cos\theta,y+sin\theta)$,为了避免交叉,利用树的结构进行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\n",(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\n",-x,-y);
    sort(ans+1,ans+cnt+1);
    n=unique(ans+1,ans+cnt+1)-ans-1;
    printf("%d\n",n);
    for(int i=1;i<=n;i++){
        printf("%d %d\n",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)

posted @ 2020-07-05 21:13  Echo宝贝儿  阅读(202)  评论(0编辑  收藏  举报