ZZULIOJ题解

本文介绍了几个编程题目,包括电梯运行时间计算、小球滚动的最短和最长时间、众数问题、破解简单密码、统计立方数、等值数目、海选女主角等,涉及算法和逻辑推理,展示了如何使用C++解决这些问题。

目录

1221.电梯

1222.小球滚动问题

1205.你爱我吗?

1201.众数问题

1214.盐水的故事

1215.破解简单密码

1217.统计立方数

1226.等值数目

1241.人见人爱A+B

1249.成功学生人数

1232.公交车之谜

1234.我爱淘宝

1237.童鞋你多大了?

1238.学长的鸡蛋

1239.K-String

1243.海选女主角

1296.a/b+c/d

1275.找数

1274.位数和

1279.一只小蜜蜂 

1299.连通图

1316.最高奖学金

1305.选数

1358.相邻素数距离

1473.奇怪的排序

1203.做幻方


1221.电梯

题目描述

在某一高层建筑内只有一部电梯,当你按下一个数时,电梯会运行到那一层。已知电梯每上升一层需6秒,下降一层需4秒,在需要停留的那层停留5秒。现有N个整数组成的一个需求列表,电梯将依次响应,电梯从0层开始运行,而在运行过程结束之前不会返回0层。

注意,若出现相邻两个整数相等,代表在同一层执行了两个不同任务,可以理解为:电梯已经停了5秒,正要关门时又有人在同一层按开门键,电梯又开门并停留5秒。

输入

输入分两行,第一行是一个正整数N(N<=1000),代表停留几次,第二行的N个数字代表这几次依次停留的楼层。

输出

输出电梯完成该任务序列所需的时间,单独占一行。

样例输入 Copy

3

2 3 1

样例输出 Copy

41

提示

电梯从0层上升到2层运行时间为12秒,停留5秒,再上升第三层,运行时间6秒,停留5秒,再下降到第一层,运行时间8秒,停留5秒。共41秒。

郑州轻工业大学oj上的一道基础题,使用while循环即可解决。

​#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m;//定义停留的次数,楼层数
    int sum=0,i=0;//初始时间和楼层数
    cin>>n;
    while(n--){
        cin>>m;

        while(i<m){  //如果楼层数小于按下的楼层数,在上升
            sum+=6;
            i++;
        }
        
        while(i>m){
            sum+=4;
            i--;
        }
        
        if(i==m) sum+=5;//到了这一层,停留5秒
    }
    
    cout<<sum<<endl;
    return 0;
}

1222.小球滚动问题

题目描述

有n个小球以每秒1cm的速度在一个滑槽上滑行,滑槽没有封口,所以当小球滑到滑槽的端点时将会掉落下来。滑槽的宽度只容许一个小球通过,小球之间的碰撞为弹性碰撞(即碰撞后小球速度的绝对值不变,方向相反)。

已知n个小球的初始位置,但不知道小球的朝向,小球与槽之间的摩擦力不计,请你计算所有小球掉下所需要的最短和最长时间(秒)。

输入:
第一行输入一个整数L表示滑槽的长度(单位:cm)(1<=L<=10^6);
第二行输入一个整数n代表小球的个数(1<=n<=10^6);
第三行输入n个整数,第i个整数Xi(1<=Xi<=L)代表第i个小球的初始位置(即,距离滑槽左端Xi厘米)
输出 :
输出一行两个整数,分别代表所有小球掉落的最短和最长时间(秒)
样例输入:
10
3
2 6 7
样例输出:
4 8

我们可以知道,当没有发生碰撞时,最后一个小球下洛的时间是所有小球下落的最短时间。

我们用q[]数组存每个小球的位置,由于不知道小球从哪边下落,对于每一个小球而言,如果没有发生弹性碰撞时,离最近的槽边滑出时,时间最短。

代码段如下:

for(int i=1;i<=n;i++) 
    cin>>q[i];//存每个小球的位置sort(q+1,q+n);//对小球的位置进行排序for(int i=1;i<=n;i++) 
    b[i]=min(q[i],L-q[i]);//存离哪个槽边最近的距离int maxi=b[1];

for(int i=2;i<=n;i++)
    if(maxi<b[i]) maxi=b[i];//找到最后一个小球下落的时间,为所有小球下落最短时间

cout<<maxi<<" ";//优先输出最短时间

我们如何找最长时间呢?

同意的,我们可以找没有发生碰撞的最长时间,和发生碰撞的最长时间,最后比较哪一个大。

而没有发生碰撞的,又分为所有小球都往左方向滑动 ,所有小球都往右,我们找出两者的最大值。

由于所有小球离左端的距离在上面都是排好序的,则q[n]是离左端最大的距离,在所有小球往左滑动时,时间最大,同理,L-q[1] 是所有往右小球时间最大的一个,则此阶段的代码如下:

int max1=max(q[n],L-q[1]);//max1是所有没有发生碰撞时,所耗时间最大

而最后,就是最难理解的发生碰撞时的了,我们如何去讨论呢?

我们不妨假设第一个小球与第二个小球发生碰撞时,第三个小球往后所有的小球都向右移动,也就是说,除了第一个小球和最后一个小球,其他小球都是可以和左边或者右边的小球发生碰撞的。

我们不妨将此阶段又划分为两类:往右碰撞往左回,往左碰撞往右回 。

可能画出图比较好理解些:

编辑

这是往左碰撞往右弹,由于两者的速度相等,则i走的距离为l[i]=L-q[i]+q[i]-q[i-1],化简为l[i]=L-q[i-1],有点神奇哈,竟然可以消掉!

同理,往右碰撞往左回,r[i]=q[i]+q[i+1]-q[i],化简得r[i]=q[i+1]。

但是,我们刚刚护理了第一个和最后一个,我们添上:r[1]=q[2]-q[1],l[n]=L-q[n-1]。

接下来,我们上完整的代码:

#include<bits/stdc++.h>
#include<vector>
#include<string>
#include<algorithm>
#include<math.h>
using namespace std;
const int N=1e6+10;
int q[N],b[N],l[N],r[N];
int main()
{
    int L,n;
    cin>>L>>n;
    for(int i=1;i<=n;i++) cin>>q[i];
    sort(q+1,q+n);
    for(int i=1;i<=n;i++){
        b[i]=min(q[i],L-q[i]);
    }
    int maxi=b[1];
    for(int i=2;i<=n;i++){
        if(maxi<b[i]) maxi=b[i];
    }
    cout<<maxi<<" ";
    int max1=max(q[n],L-q[1]);
     
    for(int i=2;i<n;i++){
        l[i]=L-q[i-1];
        r[i]=q[i+1];
    }
    r[1]=q[2]-q[1];
    l[n]=L-q[n-1];
    int ma1=l[0];
    for(int i=2;i<=n;i++)
        if(l[i]>ma1) ma1=l[i];
    int ma2=r[0];
    for(int i=2;i<=n;i++)
        if(r[i]>ma2) ma2=r[i];
    cout<<max(max1,max(ma1,ma2));
    return 0;
}

1205.你爱我吗?

题目描述

LCY买了个n束鲜花准备送给他暗恋的女生,但是他不知道这个女生是否喜欢他。这时候一个算命先生告诉他让他查花瓣数,第一个花瓣表示“爱”,第二个花瓣表示“不爱”,第三个花瓣表示“爱”......为了使最后的结果是爱,LCY需要从n束花中选出一些,你能帮他算出最后他送给女生的花中最多包含多少个花瓣吗?

输入

首先输入一个数T,表示测试的组数。

接下来T组测试实例,每组实例首先输入一行,包括一个整数n(1<=n<=100)。

然后输入一行,n个整数a1,a2,...,an(1<=ai<=100),表示每束花包含的花瓣的个数。

没有答案输出0

样例

输入
3
1
1
1
2
3
5 6 7
输出
1
0
13

我们发现只有最后是奇数时,才是“爱”, 而且如果是偶数的话,我们应该减去最小的奇数,因为偶数-奇数=奇数,如果所有花瓣中没有奇数,那么输出0.

代码如下:

#include<bits/stdc++.h>
using namespace std;
constint N=1e6+10;
int q[N];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int sum=0;
        memset(q,0,sizeof(q));//初始化int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&q[i]);
            sum+=q[i];
        }
        sort(q+1,q+n);//排序int y=0;
        for(int i=1;i<=n;i++)
        {
            if(q[i]%2!=0)//找到第一小的奇数
            {
                y=q[i];break;
            }
        }
        if(y==0&&sum%2==0) printf("0\n");//如果没有奇数并且sum和为偶数,则输出0else{
            if(sum%2==0) sum-=y;
                printf("%d\n",sum);
        }
   }
        return 0;
}

1201.众数问题

问题描述

给定含有n个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数。多重集S中重数最大的元素称为众数。

例如,S={1,2,2,2,3,5}。多重集S的众数是2,其重数是3.

对于给定的由n个自然数组成的多重集合S,计算S的众数和重数。

输入
第一行多重集S中元素的个数n(n<=50000);接下来的n行中,每行有一个自然数。
输出
输出文件有两行,第一行给出众数,第二行给出重数。(如果有多个众数,只输出较小的)。
样例输入
6
1
2
2
2
3
5
样例输出
2
3

一般的朴素做法

#include<bits/stdc++.h>
using namespace std;
constint N=1e6+10;
int q[N],vis[N];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&q[i]);
        vis[q[i]]++;//记录这个数出现的次数
    }
    
    int max1=q[1];
    for(int i=2;i<=n;i++)
        if(max1<q[i]) max1=q[i];//找最大的下标int max2=1;
    for(int i=1;i<=max1;i++)
    {
        if(vis[i]>vis[max2])
            max2=i;
    }
    printf("%d\n%d",max2,vis[max2]);
    return 0;
}

暴力做法

#include<bits/stdc++.h>
using namespace std;
constint N=1e6+10;
int max,t,ans,q[N],vis[N];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
        scanf("%d",&q[i]);
    for(int i=1;i<=n;i++)
    {
        ans=1;
        for(int j=i+1;j<=n;j++)
            if(q[i]==q[j]) ans++;
        vis[i]=ans;
    }
    for(int i=1;i<=n;i++)
        if(vis[i]>max)
        {
            max=vis[i];
            t=q[i];
        }
    printf("%d\n%d",t,max);
    return 0;
}

最后一种方法,我想到的就是排序加双指针,但一直AC不了,也不知道怎么回事。

我将思想说一下,比如1 2 3 2 2 经过排序之后1 2 2 2 3,然后我们用双指针。

for(int i=1;i<=n;i++)
{
    int ans=1;
    int j=i+1;
    
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值