zoukankan      html  css  js  c++  java
  • 20171008 校内模拟赛 题解

    L(chess)
    【题目描述】
    BBS 喜欢和 LGH 下棋,因为这样能增长他的 LG 技巧。今天他们又开始下棋。 BBS 想知
    道,以当前的局势,如果双方都以最优策略下棋,那么谁能获得胜利呢?毕竟如果这局会输,
    就可以马上用 LFF清理大师清理桌面以保持他的 100%的胜率。
    棋盘是一个 8*8 的方格。 BBS 执白,棋子用’W’表示;LGH 执黑,棋子用’B’表示。规则
    是这样的:棋盘上为’.’的位置是空格。对于 BBS 来说,如果他有一个棋子在(r,c)的位置且(r-
    1,c)的位置为空格,那么他可以将这个棋子移到(r-1,c)的位置,如果他将任意一个棋子移到了
    (1,c),那么他将立即获得胜利。对于 LGH 来说,如果他有一个棋子在(r,c)的位置且(r+1,c)的
    位置为空格,那么他可以将这个棋子移到(r+1,c)的位置,如果他将任意一个棋子移到了(8,c),
    那么他将立即获得胜利。由于 BBS非常的 B,所以总是他先手移动一个棋子,然后交换移动
    权。现在给你整个棋盘,请你输出这局的结果。
    【输入描述】
    输入一个 8*8的棋盘,由’W’,’B’或’.’组成。保证此时第一行没有 W,第八行没有 B。
    【输出描述】
    如果这盘 BBS能赢,请输出”BBS”;如果这盘 LGH 能赢,请输出”LGH”。
    【样例】

    ........
    ........
    .B....B.
    ....W...
    ........
    ..W.....
    ........
    ........

    【输出】

    BBS
    【说明】

    本题中,每 10%的数据包括 5 个点,只有通过全部的 5 个点才能获得这 10%的分数。  
    【题解】

    只需计算下两人的最少获胜步数然后比较即可。

    #include<cstdio>
    int b[10][10];
    int B=8,W=8;
    int main(){
        freopen("chess.in","r",stdin);
        freopen("chess.out","w",stdout);
        for(int i=1;i<=8;i++){
            for(int j=1;j<=8;j++){
                char c=getchar();
                while(c!='.'&&c!='B'&&c!='W') c=getchar();
                if(c=='.') b[i][j]=0;
                else if(c=='W') b[i][j]=1;
                else b[i][j]=2;
            }
        }
        for(int i=1;i<=8;i++){
            for(int j=1;j<=8;j++){
                if(b[i][j]==1){
                    int ok=1;
                    for(int k=1;k<i;k++){
                        if(b[k][j]==2) ok=0;
                    }
                    if(ok) if(i-1<W) W=i-1;
                }
                if(b[i][j]==2){
                    int ok=1;
                    for(int k=i+1;k<=8;k++){
                        if(b[k][j]==1) ok=0;
                    }
                    if(ok) if(8-i<B) B=8-i;
                }
            }
        }
    //    printf("%d %d
    ",B,W);
        if(B<W) puts("LGH");
        else puts("BBS");
        return 0;
    }

    G(tree)
    【题目描述】
    BBS 有一个 n 个点的树,现在告诉你这 n-1条边两端的点, 由于他非常 B,所以希望你
    能帮他把这棵树放到平面直角坐标系上,并满足以下条件,要不然 BBS 的强迫症会发作:
    1. 不 B 不行:每个点的坐标必须为整点,即 x,y 均为整数。同时点的坐标两两不同且
    坐标绝对值小于 10^18。
    2. 不 B 不行:每条树边都必须平行于 x 轴或 y 轴。
    3. 不 S 不行:不能有任意两条树边在非树点处相交。
    【输入描述】
    第一行为一个整数 n,表示树点的数量。
    接下来的 n-1行,每行两个整数 p[i]和 q[i], 表示点 p[i]和点 q[i]有连边。
    【输出描述】
    第一行输出”YES”或”NO”。 如果能将这棵树放到平面直角坐标系上且满足所以条件, 输
    出”YES”, 否则输出”NO”。
    如果第一行输出”YES”, 那么接下来的 n 行,每行输出两个整数 x[i],y[i], 表示点 i 的坐标
    为(x[i],y[i])。
    如果有多种解,允许输出任意一种。
    【样例】

    7
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7

    【输出】

    YES
    0 0
    1 0
    0 1
    2 0
    1 -1
    -1 1
    0 2

    【数据范围】
    对于 100%的数据, 1<=n<=30
    本题中,每 10%的数据包括 6 个点,只有通过全部的 6 个点才能获得这 10%的分数

    【题解】

    首先如果有一个点连接了超过 4 条边,那么无法建图。
    然后我们可以选取一个点放在原点,然后 DFS 建树。如果当前点和原点直接相连,那么
    当前点和原点直接连一条长度为 2^30 的边;如果当前点到原点中间要经过 i 个点,那么当前点
    和上一个点连一条长度为 2^(30-i)的边。这样连边可以保证没有两条线相交。

    #include<cstdio>
    #include<vector>
    using namespace std;
    int n,X,y;
    vector<int> G[31];
    long long ax[31],ay[31];
    bool vis[31];
    int dx[5]={0,-1,1,0};
    int dy[5]={-1,0,0,1};
    void dfs(int x,int fa,long long dis){
        vis[x]=1;
        int nd=0;
        for(int i=0;i<G[x].size();i++){
            int v=G[x][i];
            if(!vis[v]){
                if(nd==3-fa) nd++;
                ax[v]=ax[x]+dis*dx[nd];
                ay[v]=ay[x]+dis*dy[nd];
                dfs(v,nd,dis/2);
                nd++;
            }
        }
    }
    int main(){
        freopen("tree.in","r",stdin);
        freopen("tree.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            scanf("%d%d",&X,&y);
            G[X].push_back(y);
            G[y].push_back(X);
        }
        for(int i=1;i<=30;i++){
            if(G[i].size()>4){
                puts("NO");return 0;
            }
        }
        ax[1]=ay[1]=0;
        dfs(1,-1,1<<30);
        puts("YES");
        for(int i=1;i<=n;i++){
            printf("%lld %lld
    ",ax[i],ay[i]);
        }
        return 0;
    }

    B(journey)
    【题目描述】
    BBS 作为一名老司机,最喜欢的自然不过开车。今天他新进口了一辆“涡轮喷压”车,
    可以在助跑至少 s个单位后在空中飞至多 d 个单位。本来开车是一件很开心的事,从石
    头上飞过去也是件很开心的事,可是两件事在一起……怎么会这样呢?瀚嵩现在在 0 的
    位置,他要开到 m 的位置,在这段路上有 n 块石头,现在他知道这 n 块石头的位置,
    他想请教你要如何开车才能经过这一段路?
    【输入描述】
    第一行有四个数,分别是 n,m,s,d
    第二行为 n 个数,是 n 个石头的位置 w[1],w[2]…w[n]
    【输出描述】
    输出有若干行,为你开车的过程,每个过程一行,方法有两种:
    1、“RUN X”这个表示在地上开 X 个单位长度,不能有两个连续的 RUN命令
    2、“JUMP X”这个表示在空中飞 X 个单位长度,这个命令的前一个操作要求要助跑
    距离超过 s,飞的长度不超过 d
    如果有多种过程能到达终点,允许输出任意一种。
    如果不能到达终点,输出“Impossible”
    【样例】

    3 10 1 3
    3 4 7

    【输出】

    RUN 2

    JUMP 3

    RUN 1

    JUMP 2

    RUN 2
    【数据范围】

    对于 40%的数据, n<=10 并捆绑测试
    对于 70%的数据, n<=100000
    对于 100%的数据,
    1<=n<=200000,2<=m<=10^9,1<=s,d<=10^9,1<=w[i]<=m-1,w[i]<w[i+1]
    X 为 1 到 10^9 内的整数

    【题解】

    将每个障碍的两端视为两个点,分为前点和后点。如果该障碍的前点和上一个障碍的后
    点之间的距离不小于 s 且该后点能到达,那么该点可以起跳。 然后将该点作为最新的起跳点
    更新后面 d 以内的前点,最后记录下方案即可。

  • 相关阅读:
    oracle笔记
    随笔
    EclipsePDT PHP的开发环境配置
    winXP的系统如何避免他人在不需要密码的情况进入安全模式
    WINDOWS图片和传真查看器找不到
    Oracle常用语句大全
    jdbc连接oracle
    jdk与jre的区别
    mysql手工注入.md
    sql手工注入.md
  • 原文地址:https://www.cnblogs.com/nzher/p/7638359.html
Copyright © 2011-2022 走看看