D题 火车购票

在这里插入图片描述
在这里插入图片描述

先来个错误示范,75分代码:

#include <bits/stdc++.h>
using namespace std;
int n,cnt,tmps,rest[110],vis[110];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=20;i++)
        rest[i]=5;//每排剩余5张票
    for(int i=1;i<=n;i++)
    {
        cin>>cnt;
        for(int j=1;j<=20;j++)//第j排
        {
            if(rest[j]>=cnt)//第j排剩余的票数大于等于cnt,则可以让cnt个座位相邻
            {
                tmps=0;//记录出票数
                for(int k=(j-1)*5+1;k<=j*5;k++)//遍历第j排座位,k为座位编号
                {
                    if(vis[k]==0)//第k个座位还未被购买
                    {
                        vis[k]=1;
                        tmps++;
                        if(tmps<cnt)
                            printf("%d ",k);
                        else if(tmps==cnt)//已经出了cnt张票了,结束
                        {printf("%d\n",k);rest[j]=rest[j]-cnt;break;}
                    }
                }
                break;
            }
        }
    }
    return 0;
}

为什么只得75分呢?

因为没考虑这种情况:当前要购买的票数大于每一排剩余的票数,这样无法保证出票的是同一排的相邻座位。举个例子,现在每一排都只剩了3个座位,而要一次购买5张票,那么只能第一排出2张票,第二排出3张票,这五张票不是都相邻的。

100分 AC代码:

#include <bits/stdc++.h>
using namespace std;
int n,cnt,tmps,flag,rest[110],vis[110];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=20;i++)
        rest[i]=5;//每排剩余5张票
    for(int i=1;i<=n;i++)
    {
        cin>>cnt;
        flag=0;
        for(int j=1;j<=20;j++)//第j排
        {
            if(rest[j]>=cnt)//第j排剩余的票数大于等于cnt,则可以让cnt个座位相邻
            {
                flag=1;//标记:可以做到cnt个座位相邻
                tmps=0;//记录出票数
                for(int k=(j-1)*5+1;k<=j*5;k++)//遍历第j排座位,k为座位编号
                {
                    if(vis[k]==0)//第k个座位还未被购买
                    {
                        vis[k]=1;
                        tmps++;
                        if(tmps<cnt)
                            printf("%d ",k);
                        else if(tmps==cnt)//已经出了cnt张票了,结束
                        {printf("%d\n",k);rest[j]=rest[j]-cnt;break;}
                    }
                }
                break;
            }
        }
        if(flag==0)//无法做到cnt个座位相邻
        {
            tmps=0;
            for(int i=1;i<=100;i++)
            {
                if(vis[i]==0)
                {
                    vis[i]=1;
                    tmps++;
                    rest[(i-1)/5+1]--;
                    if(tmps<cnt)
                        printf("%d ",i);
                    else if(tmps==cnt)
                    {printf("%d\n",i);break;}
                }
            }
        }
    }
    return 0;
}

B题 公共钥匙盒

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这题说实话,有点难度啊...

看了一下网上其他人写的题解,是写了结构体的多维排序。我的思路是遍历所有时刻,如果现在遍历的时刻有放回或取出就按题目要求进行操作。仔细想了一下,时间复杂度是O(n*n*s),极限数据可以到1e10了,竟然也给我AC了?好吧,我也只想到了暴力模拟...

如果想看多维排序解题的,可以看看这篇文章:https://blog.csdn.net/L_xqqzldh/article/details/87938066

~~假的~~100分 AC代码:

#include <bits/stdc++.h>
using namespace std;
bool vis[1010],is_out[10110],is_in[10110];
vector<int>out[10110],in[10110];
int n,m,mx,t1,t2,d,num,a[1010];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        a[i]=i;
    for(int i=1;i<=m;i++)
    {
        cin>>num>>t1>>d;
        t2=t1+d;
        out[t1].push_back(num);//保存t1时刻取出钥匙的编号(可能取出多个)
        in[t2].push_back(num);//保存t2时刻放回钥匙的编号(可能放回多个)
        is_out[t1]=1;//t1时刻有取出
        is_in[t2]=1;//t2时刻有放回
        mx=max(mx,t2);//mx为最大时刻
    }
    memset(vis,1,sizeof(vis));//开始时所有挂钩均被占用
    for(int i=1;i<=mx;i++)//遍历所有时刻
    {
        if(is_in[i]==1)//i时刻有放回(先全部放回再取出)
        {
            sort(in[i].begin(),in[i].end());//放回时要按从小到大放回
            for(int j=0;j<in[i].size();j++)
            {
                for(int k=1;k<=n;k++)
                {
                    if(vis[k]==0)//第k个挂钩没被占用
                    {
                        a[k]=in[i][j];//in[i][j]表示i时刻放回的第j把钥匙的编号
                        vis[k]=1;
                        break;
                    }
                }
            }
        }
        if(is_out[i]==1)//i时刻有取出
        {
            for(int j=0;j<out[i].size();j++)
            {
                for(int k=1;k<=n;k++)
                {
                    if(a[k]==out[i][j])//out[i][j]表示i时刻取出的第j把钥匙的编号,找到了编号为out[i][j]的钥匙,将其取出
                    {vis[k]=0;break;}
                }
            }
        }
    }
    for(int i=1;i<=n;i++)
        i==n?printf("%d\n",a[i]):printf("%d ",a[i]);
    return 0;
}

A题 打酱油

在这里插入图片描述
在这里插入图片描述
100分 AC代码:

#include <bits/stdc++.h>
using namespace std;
int n,s,t1,t2,t3,ans;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    s=n/10;
    t1=s/5;
    t2=(s-t1*5)/3;
    t3=s-t1*5-t2*3;
    ans=7*t1+4*t2+t3;
    printf("%d\n",ans);
    return 0;
}

C题 最大波动

在这里插入图片描述
100分 AC代码:

#include <bits/stdc++.h>
using namespace std;
int n,mx,a[1010];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    mx=0;
    for(int i=2;i<=n;i++)
        mx=max(mx,abs(a[i]-a[i-1]));
    printf("%d\n",mx);
    return 0;
}