题目背景
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;
}