牛客——2018年全国多校算法寒假训练营练习比赛(第一场)

这场还是新生赛,主要是模拟,搜索,递推递归,思维题。模拟手速还是慢,也会考虑不周全。

G:搜索:

链接:https://www.nowcoder.com/acm/contest/67/G
来源:牛客网

题目描述 
    圈圈圆圆圈圈,lulu小朋友最近看喜羊羊看多了,老是受刺激就画圆圈,听到小于8的数字时,还会画出十分有规律的圆圈,现在你需要根据样例观察出规律,编写程序,根据输入的数字n(n<8),输出对应的圆圈。
输入描述:
第一行是样例数T(T<9)
第2到2+T-1行每行有一个整数n(n<8),代表lulu听到的数字
输出描述:
听到对应数字时,输出对应样子的圆圈。
示例1
输入

4
0
1
2
3
输出

O
 O
O O
 O
    O
   O O
    O
 O     O
O O   O O
 O     O
    O
   O O
    O
             O
            O O
             O
          O     O
         O O   O O
          O     O
             O
            O O
             O
    O                 O
   O O               O O
    O                 O
 O     O           O     O
O O   O O         O O   O O
 O     O           O     O
    O                 O
   O O               O O
    O                 O
             O
            O O
             O
          O     O
         O O   O O
          O     O
             O
            O O
             O
说明

当n=0时输出
O
当n=1时输出
*O
O*O
*O
当n=2时输出
****O
***O*O
****O
*O*****O
O*O***O*O
*O*****O
****O
***O*O
****O
上面的'O'是大写英文字母O,'*'代表空格,每一行最后一个O后面不带空格。
备注:
对于100%的数据,
0<T<9;
0<=n<8;
代码:

#include<bits/stdc++.h>
typedef long long LL;

using namespace std;

int len[8]={1,3,9,27,81,243,729,2187};
char a[2500][2500];
string s[2500];

void dfs(int i,int j,int n)
{
    if(n==0)
    {
        a[i][j]='O';
   // cout<<"i:"<<i<<"  "<<"j"<<j<<endl;
        return;
    }
    dfs(i,j+len[n-1],n-1);
    dfs(i+len[n-1],j,n-1);
    dfs(i+len[n-1],j+2*len[n-1],n-1);
    dfs(i+2*len[n-1],j+len[n-1],n-1);

}
int main()
{
    int t,n;
    int i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=0;i<len[n];i++){
            s[i]="";
            for(j=0;j<len[n];j++)
                a[i][j]=' ';
        }
        dfs(0,0,n);
        for(i=0;i<len[n];i++)
        {
            int cnt=len[n]-1;
            while(a[i][cnt]==' ')
                cnt--;
            for(j=0;j<=cnt;j++)
                s[i]+=a[i][j];
            cout<<s[i]<<endl;
        }
    }
    return 0;
}
H:递推递归

这道题是大一时老师讲过的原题。原谅我还是自己重推了一遍

链接:https://www.nowcoder.com/acm/contest/67/H
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述 
    现在有一个大小n*1的收纳盒,我们手里有无数个大小为1*1和2*1的小方块,我们需要用这些方块填满收纳盒,请问我们有多少种不同的方法填满这个收纳盒
输入描述:
第一行是样例数T
第2到2+T-1行每行有一个整数n(n<=80),描述每个样例中的n。
输出描述:
对于每个样例输出对应的方法数
示例1
输入

3
1
2
4
输出

1
2
5
说明

n=4,有五种方法
1:1 1 1 1
2:2 1 1
3:1 2 1
4:1 1 2
5:2 2
备注:
对于100%的数据,
0 < T < 80;
0 < n <= 80。

代码:

#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
    int n,t;
    long long a[101];
    long long b[101];
    a[1]=1;
    a[2]=2;
    a[3]=3;
    for(int i=4;i<=100;i++)
    {
        a[i]=a[i-1]+a[i-2];
    }
    while(~scanf("%d",&t))
    {
        for(int i=1;i<=t;i++)
        {
            cin>>b[i];
        cout<<a[b[i]]<<endl;
        }
    }
}

三。暴力水题

链接:https://www.nowcoder.com/acm/contest/67/I
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述 
    lulu喜欢小于等于1000的正整数,但是如果某个数是a或b的倍数,lulu会讨厌这个数。如果某个数里包含了a和b两个数里包含的数,lulu也会讨厌。(例如a=14,b=23,如果数字中包含1、2、3、4这四个数中的任意一个数,lulu就会讨厌这个数)。现在告诉你a,b,你能说出lulu喜欢的数有多少个么。
输入描述:
第一行是样例数T
第2到2+T-1行每行有2个整数a b。
输出描述:
输出lulu喜欢的数的个数
示例1
输入

3
2 3
14 23
1234 5678
输出

171
190
7
说明

a=1234 b=5678的时候,只考虑含有数字9,0的数,只有7个,分别是9,99,999,90,990,909,900
备注:
对于100%的数据,
0 < T <= 20;
0 <= a <= 99999;
0 <= b <= 99999。
代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int num[11];
int like;
void chai(int a,int b)
{
    memset(num,0,sizeof(num));
    while(a>0)
    {
        int hh=a%10;
        num[hh]=1;
        a=a/10;
    }
    while(b>0)
    {
        int hh=b%10;
        num[hh]=1;
        b=b/10;
    }
}
int main()
{
    //cout<<999%10<<endl;
    int a,b;
    int t;
    while(~scanf("%d",&t))
    {
        for(int i=1;i<=t;i++)
        {
        cin>>a>>b;
        like=0;
        chai(a,b);
        for(int i=0;i<=1000;i++)
        {
            if(i%a==0||i%b==0)
            continue;
            if(i>=1&&i<10)
            {
                if(num[i]==1)
                continue;
            }
            else if(i>=10&&i<100)
            {
                if(num[i%10]==1||num[i/10]==1)
                    continue;
            }
            else if(i>=100&&i<1000)
            {
                if(num[i%10]==1)
                    continue;
                if(num[i/100]==1)
                    continue;
                if(num[(i/10)%10]==1)

                    continue;
            }
            else if(i==1000)
            {
                if(num[0]==1||num[1]==1)
                    continue;
            }
            //cout<<"i"<<i<<endl;
            like++;
        }
        cout<<like<<endl;
        }
    }
    return 0;
}
还有两道模拟题,一直未过。。再模拟两遍试试。

A:吃鸡

这道题就是很简单的没有思维的模拟。

题目:

链接:https://www.nowcoder.com/acm/contest/67/A
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述 
    在绝地求生(吃鸡)游戏里,不同的枪支有不同的威力,更是可以搭配不同的配件,以提升枪支的性能。

    每一把枪都有其威力及其可装备配件种类。每一个配件有其所属种类,可以为枪支提供威力的百分比加成。每一把枪只能装备一个同类配件。给你n把枪支和m个配件,枪的威力为p,可装备的配件数量为k,为k个不同类型的配件,同种类配件只可以装备一个。配件种类用数字q表示,配件威力加成用一个小数b表示。请你挑选一把枪并为其搭配配件使其威力最大。
    假设一把枪的威力是p,装配的k个配件的威力加成是bi,那么枪最后的威力w=p*(1+b1+b2+…+bk)。


输入描述:
数据有多组,处理到文件结束。
第一行两个整数n和m,代表枪支数量和配件数量。
接下来n行,描述n把枪的属性:第一个整数为p,代表枪支的威力;第二个整数为k,代表该枪支可装备的配件数量;后面k个整数,代表可装备配件的种类。
接下来m行,描述m个配件的属性:第一个整数为q,代表配件的种类,第二个浮点数为b,代表配件可以为枪支提供的威力加成。
输出描述:
每组数据输出为一行,输出一个浮点数,代表合理装备配件后的枪支最大威力。精确到小数点后4位。
示例1
输入

3 6
120 3 1 2 3
100 4 1 2 3 4
110 3 2 3 4
1 0.12
2 0.23
2 0.26
4 0.57
3 0.35
5 0.41
输出

239.8000
说明

对于上面的样例,正确答案应该是,使用第三把枪,配上第三、四、五个配件。
枪的最终威力就是110*(1+0.26+0.57+0.35)=239.8
备注:
对于100%的数据,
1 <= n,m,k,q <= 1000;
0 <= p <= 1000;
0 <= b <= 1。
我的代码:

#include<iostream>
#include<stdio.h>
using namespace std;
double shuchu[1010];
double xpp;
struct node
{
    int p;
    int k;
    int zhonglei[1010];
}qiang[1010];
struct node1
{
  // int p;
   double b;
   int logal;
}peijian[1010];

int main()
{
    int n,m;
    int p;
    double b;
    int num=0;
    long double lala;
    long double sum;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=1000;i++)
        {
            peijian[i].logal=0;
        }
        for(int i=1;i<=n;i++)
        {
            cin>>qiang[i].p>>qiang[i].k;
            for(int j=1;j<=qiang[i].k;j++)
            {
                cin>>qiang[i].zhonglei[j];
            }
        }
        for(int i=1;i<=m;i++)
        {
          cin>>p>>b;
          if(peijian[p].logal==1)//表明这个配件之前有了
          {
              if(peijian[p].b<b)
                peijian[p].b=b;
          }
          else
          {
              peijian[p].b=b;
              peijian[p].logal=1;
          }
        }


        xpp=0;

        for(int i=1;i<=n;i++)
        {
            lala=1;
             sum=qiang[i].p;

            for(int j=1;j<=qiang[i].p;j++)
            {
               lala=lala+peijian[qiang[i].zhonglei[j]].b;
            }
            lala=lala*qiang[i].p;
           // cout<<"lala:"<<lala<<endl;
            if(lala>xpp)
                xpp=lala;
        }
       // cout<<xpp<<endl;
        printf("%.4lf\n",xpp);
        

    }
    return 0;
}
代码2:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,k[1005],p[1005],q[1005][1005],a;
double b[1005],s,sum,ans;
  
int main()
{
    while(cin>>n>>m)
    {
        ans=0;
        memset(b,0,sizeof(b));
    for(int i=1;i<=n;i++)
    {
        cin>>p[i]>>k[i];
        for(int j=1;j<=k[i];j++)
        cin>>q[i][j];
    }
    for(int i=1;i<=m;i++)
    {
        cin>>a>>s;
        b[a]=max(b[a],s);
          
    }
    for(int i=1;i<=n;i++)
    {
        s=1;
        for(int j=1;j<=k[i];j++)
        s+=b[q[i][j]];
        sum=p[i]*s;
        ans=max(ans,sum);
    }
    printf("%.4lf\n",ans);
    }
}
值得学习的地方是,我用的struct进行枪与配对配件的配对,代码2直接用二维数组表示,而且代码一太繁琐,中间判断最大的那个时写的也很啰嗦。这也是我写代码最应该改进的地方。

F:吃鸡——跑毒篇

这道题感觉就是要想透彻,一定要看样例。将问题简单化反而更好。

题目:

链接:https://www.nowcoder.com/acm/contest/67/F
来源:牛客网

题目描述 
    现在有一款很火的游戏playerunknown's battlegrounds,人称“吃鸡”,在里面经常面临跑毒(从安全区外跑进安全区内)的问题,在安全区外,人们会处于中毒状态,每秒会掉a%血,人们可以通过使用道具急救包把血量升回到80%,使用急救包需要原地站着6秒。现在知道在安全区外扣血速度为a%/s,角色和安全区的距离为b米,角色跑步速度为1m/s,角色有c个急救包,请问角色是否能安全跑进安全区内。(PS:角色开始的血量为100%。如果血量降到0%,立刻判定为死亡。使用急救包时,如果刚使用完毕瞬间或者正在使用急救包的时候,血量降到0%,角色立即判定为死亡。顺带一提,这里判断时间不存在0.xxxx秒,最小时间单位为1s)
输入描述:
第一行是样例数T(T<9)
第2到2+T-1行每行有三个整数a b c,其中a为安全区外的扣血速度a%/s,b为角色和安全区的距离,c为急救包的数量。
输出描述:
如果角色能进入安全区输出“YES”。
若角色在安全区外死亡输出“NO”。
示例1
输入

3
1 100 2
6 31 2
7 31 2
输出

YES
YES
NO
说明

当a=6,b=31,c=2时,
0s起跑,10s的时候角色跑了10M,血量剩下40%,开始使用急救包,16s的时候,角色血量先降到4%再恢复到80%,然后角色继续跑步。23s的时候,角色跑了17M,剩余血量为38%,开始使用急救包,29s的时候,角色血量先降到2%再恢复到80%,然后角色继续跑步。42s的时候,角色跑了30m,血量剩余2%。当43s的时候,角色跑了31m进入了安全区内,不再扣血。
备注:
对于100%的数据,
1 <= T < 9;
0 < a <= 20;
0 < b <= 120;
0 <= c <= 8。


附上通过样例为90.91%的代码以及大神的代码:

#include<stdio.h>
int main()
{
    int t,a,b,c,hp;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&a,&b,&c);
        hp=100;
        while(b>1)
        {
            if(hp<=7*a&&c)
            {
                hp=80;
                c--;
            }
                hp-=a;
                b--;
        }
        if(hp>0)
            printf("YES\n");
        else
            printf("NO\n");
    }
}


#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int a,b,c,c22;
        cin>>a>>b>>c;
        c22=c;
        int xueliang=100;
        int time=0;
        int jixian=6*a;
        int logal=0;
        int k=0;//表示用的急救包的次数
        while(1)
        {
            if(b<=1)
                break;
            if(c==0)
            {
                if(c22!=0)
                {
                    if(time+80/a>b-1)
                    logal==0;
                    else
                    logal=1;
                  
                    break;
                }
                else if(c22==0)
                {
                    if(time+100/a>b-1)
                    logal==0;
                    else
                    logal=1;
                    break;
                }
            }
            xueliang=xueliang-a;
            time++;//过了一秒钟,走了1米
            if(time>=b)
            {
                break;
            }
            if(xueliang-jixian<a)
            {
                c--;
                if(c<0)
                {
                    logal=1;
                    break;
                }
                xueliang=80;
                continue;
            }
        }
        if(logal==1)
            cout<<"NO"<<endl;
        else
            cout<<"YES"<<endl;
    }
    return 0;
}
代码简洁是我要追求的。







  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值