如何成功签到&&模拟

题目背景

zxls组织了一场比赛,每支队伍都需要进行签到,签到在软院205进行,205布置有三个桌子以供不同队伍的队伍同时签到,一个桌子在任意时刻都至多只能有一支队伍签到,一支队伍只需在一张桌子前完成签到即可。如果三个桌子都有队伍在签到,其它需要签到的队伍就需要在任意一个桌子前排队,等待签到。

题目描述

我们假设在t=0的时刻开始接受签到,n支队伍分别在a1,a2,…,an时刻到达205,每支队伍完成签到均需M的时间,为使问题简单,我们忽略队伍在205中移动的时间。你需要告诉zxls至少在哪个时刻,所有的队伍均签到完成。

输入格式:

第一行是一个整数T,表示数据组数。
每组数据的第一行是一个整数n,表示签到的队伍数。
接下来一行有n个整数ai,表示第i支队抵达软院205的时刻。
每组的最后一行是一个整数M,表示一支队伍完成签到的时间。

输出格式:

对于每组数据,输出最后一支队伍最早签到完成的时刻。

输入样例#1:

2
5
1 2 4 5 7
4
7
4 4 4 2 8 9 11
5

输出样例#1:

11
17

说明

1≤T≤250
1≤n≤600
0≤ai≤104
1≤b≤1500

题解

这个题在开始的时候我的思路是用队列的知识来做,奈何学艺不精,忘了咋用了,眼看时间只剩下五分钟,在我马上要放弃的时候忽然想到了做贪心时用到的结构体的方法:第一项表示第i支队伍开始签到的时间,第二项表示第i支队伍签到完成的时间,于是就很简单了。但手速太慢,比赛结束一分钟后才做出来T^T。

代码

#include<cstdio>
#include<algorithm>
using namespace std;

typedef struct
{
    int a;
    int b;
} P;
P arr[1000];        //定义一个结构体数组。

int main()
{
    int T,n,m;
    int l[605];
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%d",&l[i]);        //先将各队伍到达时间储存在数组中。
        scanf("%d",&m);
        sort(l,l+n);            //按到达的先后顺序排序。
        int a=0;
        for(int i=0; i<n; i++)
        {
            if(i<=2)        //前三个直接放在结构体中。
            {
                arr[i].a=l[i];
                arr[i].b=l[i]+m;
            }
            else        //从第四个往后,把他们的到达时间与前面第三个的结束时间比较,
                        //如果结束比较早,则放入到达时间,反之放入结束时间。
            {
                arr[i].a=max(l[i],arr[i-3].b);
                arr[i].b=arr[i].a+m;
            }
        }
        printf("%d\n",arr[n-1].b);          //第n个的第二项即为签到完成的时间。
    }
    return 0;
}

用队列AC代码

#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
    int n,m,T;
    int l[1000];
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%d",&l[i]);
        scanf("%d",&m);
        sort(l,l+n);           //此部分往前都是输入内容,不用解释。
        if(n<=3)         //分情况,若n<3直接输出。
        {
            printf("%d\n",l[n-1]+m);
        }
        else            //n>3的情况。
        {
            queue<int>p1;           //定义一个队列p1。
            p1.push(l[0]+m);
            p1.push(l[1]+m);
            p1.push(l[2]+m);           //向队列中加入前三名到达的队伍的签完到的时间。
            int i=3;
            while(i<=n-1)
            {
                int a=p1.front();
                if(a>=l[i])             //若第i个到达的队伍到达时间比前数第三个早。
                {
                    p1.push(a+m);              //向队尾加入第i个队伍的结束时间。
                    p1.pop();               //删除首元素。
                    i++;
                }
                else             //若第i个到达的队伍到达时间比前数第三个晚。
                {
                    p1.push(l[i]+m);           //向队尾加入该队伍到达后+签到时间。
                    p1.pop();            //删除首元素。
                    i++;
                }
            }
            int b=p1.back();             //队列最后一个元素即为签到完成时间。
            printf("%d\n",b);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43105110/article/details/88128129
今日推荐