zoukankan      html  css  js  c++  java
  • 20171008校内训练

    普及难度我居然没AK。。。(其实我T3会,把点看成线段了,并且起点和终点没加特判

    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”。

    【样例】

    输入1

    输出1

    ........

    ........

    .B....B.

    ....W...

    ........

    ..W.....

    ........

    ........

    BBS

    输入2

    输出2

    ..B.....

    ..W.....

    ......B.

    ........

    .....W..

    ......B.

    ........

    ........

    LGH

    【说明】

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

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

    注意:如果一个W上方有棋子或者一个B下方有棋子。那么这个W或B不更新最小步数(过不去)

    如果棋子是自己的,那么选那个棋子肯定更优,所以不要管是谁的棋子

    #include<iostream>
    #include<cstdio>
    using namespace std;
    char c[10][10];
    int min1=999999999,min2=999999999;
    int main()
    {
        //freopen("chess.in","r",stdin);freopen("chess.out","w",stdout);
        for(int i=0;i<8;i++)scanf("%s",c[i]);
        for(int i=0;i<8;i++)
        for(int j=0;j<8;j++)
        {
            bool ok=0;
            for(int k=0;k<i;k++)if(c[k][j]!='.'){ok=1;break;}
            if(!ok&&c[i][j]=='W')min1=min(min1,i);
            ok=0;
            for(int k=i+1;k<8;k++)if(c[k][j]!='.'){ok=1;break;}
            if(!ok&&c[i][j]=='B')min2=min(min2,7-i);
        }
        min1<=min2?puts("BBS"):puts("LGH");
        return 0;
     } 
    View Code

    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个点有连边,那么一定无解,否则有解。

    那么要怎么构造解呢?

    我们把1号点放在(0,0)的位置上(作为树根),然后选一个很长的长度(10^15之类)的作为这个点与它能走到的点之间的距离,然后往上下左右四个方向拓展

    然后递归调用,对于一个点,从它出发的距离为它到它父亲的距离/2-1(这样能保证不会交其他树边)且它不能从它父亲来的方向回去,然后往其他三个方向拓展

    然后树大概就是这样

    记录下每个点的坐标。最后输出坐标就好了

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int g[31][5];
    long long x[31],y[31];
    bool ins(int a,int b)
    {
        for(int i=1;i<=4;i++)if(!g[a][i])return 0*(g[a][i]=b);
        return 1;
    }
    void solve(int k,int fa,int fx,long long len)//1↑4↓2←3→ 
    {
        if(fx==1)x[k]=x[fa],y[k]=y[fa]+len;
        if(fx==2)x[k]=x[fa]-len,y[k]=y[fa];
        if(fx==3)x[k]=x[fa]+len,y[k]=y[fa];
        if(fx==4)x[k]=x[fa],y[k]=y[fa]-len;
        int j=0;
        for(int i=1;i<=4;i++)
        {
            if(g[k][i]==fa||!g[k][i])continue;
            j++;if(j+fx==5)j++;solve(g[k][i],k,j,len/2-1);
        }
     } 
    int main()
    {
        freopen("tree.in","r",stdin);freopen("tree.out","w",stdout);
        int n;scanf("%d",&n);bool ok=0;
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            if(ins(u,v))ok=1;
            if(ins(v,u))ok=1;
        }
        if(ok)return 0*puts("NO");
        x[1]=0;y[1]=0;
        for(int i=1;i<=4;i++)
        {
            if(!g[1][i])break;
            solve(g[1][i],1,i,100000000000000ll);
        }
        puts("YES");
        for(int i=1;i<=n;i++)cout<<x[i]<<" "<<y[i]<<endl;
        return 0;
     } 
    View Code

    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内的整数

    贪心。

    如果两个相邻石头之间的距离够助跑,那么再前一个石头位置+1降落,在后一个石头位置-1起飞即可。这样能使接下来能飞行时间最大化

    如果不够助跑,那只能飞咯。如果当前石头位置+1-起飞的位置距离大于能飞行的距离,输出Impossible。

    注意点在文章开头。

    对于起点的特判,如果0~第一块石头位置-1都不够助跑的话,输出Impossible。

    对于终点的特判,如果飞行距离不够到最后一块石头的位置+1,输出Impossible,否则在最后一块石头的位置+1处降落,开到终点就好了

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int ok[1000100];//正run,负jump 
    int a[200100];
    int main()
    { 
    freopen("journey.in","r",stdin);freopen("journey.out","w",stdout);
        int n,m,s,d;scanf("%d%d%d%d",&n,&m,&s,&d);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);a[0]=-1;
        int tot=0,last;//起飞的位置 
        if(a[1]-1>=s){last=a[1]-1;ok[++tot]=a[1]-1;}
        else return 0*puts("Impossible");
        for(int i=2;i<=n;i++)
        {
            if(a[i]-a[i-1]-2>=s)
            {
                ok[++tot]=-(a[i-1]-last+1);
                last=a[i]-1;
                ok[++tot]=a[i]-a[i-1]-2;
            }
            else if(a[i]-last+1>d)return 0*puts("Impossible");
        }
        if(a[n]-last+1>d)return 0*puts("Impossible");
        else 
        {
            ok[++tot]=-(a[n]-last+1);
            if(m-(a[n]+1)!=0)ok[++tot]=m-(a[n]+1);
        }
        for(int i=1;i<=tot;i++)
        {
            if(ok[i]>0)printf("RUN %d
    ",ok[i]);
            else printf("JUMP %d
    ",-ok[i]);
        }
        return 0;
     } 
    View Code

    不得不说,这3题代码量是真的小

  • 相关阅读:
    看看大对象是如何爆你的内存
    Web Api 多项目文档生成之SwaggerUI
    react-native执行 npm install cl.exe找不到 的问题
    在SourceTree中使用Git submodule
    [ElasticSearch] 如何使用中文分詞ik與繁簡轉換stconvert插件
    [Activator-HelloAkka] Create our Actors
    [Activator-HelloAkka] Define our Actors
    [Activator- HelloAkka] Define our Messages
    [Scala] Currying
    [Scala] Pattern Matching(模式匹配)
  • 原文地址:https://www.cnblogs.com/lher/p/7638115.html
Copyright © 2011-2022 走看看