蓝桥杯(招募队员【算法赛】)
问题描述
为了对抗蠢蠢欲动的异能兽,炎龙侠、飞鹰侠、黑犀侠、雪獒侠和地虎侠五位铠甲勇士决定各自组建战队,迎战强敌。
消息一出,光影村的铠甲后人热血沸腾,纷纷组队报名。
现共有 n 支队伍,每支队伍由五名年轻小伙组成,他们各自填写了最想跟随的铠甲勇士编号(1 代表炎龙侠,2 代表飞鹰侠,以此类推,5 代表地虎侠)。用 ai,j表示第 i 支队伍的第 j 名队员最想跟随的铠甲勇士的编号。例如,a3,2=4 就表示第 3 支队伍的第 2 名队员想加入雪獒侠的战队。
为了公平公正,每位铠甲勇士需从报名队伍中选择一个连续的区间 [l,r](1≤l≤r≤n)进行招募。但有一个重要的规则:对于区间内的每一支队伍,该铠甲勇士必须且只能招募一名心仪他的队员。如果某支队伍中没有队员想跟随这位铠甲勇士,那么这位铠甲勇士就不能选择包含这支队伍的区间。
现在,五位铠甲勇士都想知道自己最多能招募到多少队员,以便制定最佳的作战策略。你能帮助他们计算出各自可招募的最大人数吗?
输入格式
第一行包含一个整数 n(1≤n≤105),表示报名队伍的总数。
接下来 n 行,每行包含五个整数 ai,1,ai,2,ai,3,ai,4,ai,5(1≤ai,j≤5),表示第 i 支队伍中五名队员想跟随的铠甲勇士编号。如:
5
1 2 3 4 5
1 2 3 4 5
1 1 1 1 1
1 2 3 4 5
1 2 3 4 5
输出格式
输出一行,包含五个整数,分别表示炎龙侠、飞鹰侠、黑犀侠、雪獒侠和地虎侠最多能招募到的队员数量。
5 2 2 2 2
思路
当我们解析题目我们就不难发现,要解决这个问题,我们需要为每个铠甲勇士找到最大的连续区间,使得在这个区间内每支队伍至少有一名队员想跟随该铠甲勇士。
具体来讲,如果炎龙铠甲(1),那么如果第 n-1 支队伍不含 1,而第 n 支队伍含 1,那么后续含 1 的连续队伍数即是本区间所能招到的人数。
则我们运用类似动态规划的思想,取当前招到的最大人数与在某一区间招到的人数的较大值来更新最大人数,当我们扫描完所有区间后即可得到最大队员数。
Code(C)
为便于理解本代码将数据存储在相应数组中,如炎龙铠甲为 1,则players[1]为炎龙铠甲最多招募到队员数,variable[1]为炎龙铠甲在某个区间的招募队员数……
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[])
{
// 请在此输入您的代码
int amount;
int players[6] = {0};//每个铠甲勇士招募到的人员数量
int variable[6] = {0};//一个区间的招募人数,用于寻找最大人数
scanf("%d",&amount);//输入队伍数量
for(int i = 0;i <= amount;i++){
int mark[6] = {0};//初始化,没有在该组招到队员
for(int j = 1;j <= 5;j++){
int x;
scanf("%d",&x);
if(!mark[x]){//该队伍还没有招募过,则可招募(确保同一队只能招募一次)
mark[x] = 1;//标记为已经招到
variable[x]++;//该区间招募到的队员数加一
}
}
for(int j = 1;j <= 5;j++){
if(!mark[j] || i == amount - 1){//未找到的终止,并选出最大值
players[j] = fmax(players[j],variable[j]);//从当前最大队员数与该区间可招队员数中取较大值,并更新最大队员数
variable[j] = 0;//重置该区间最大人数
}
}
}
for(int i = 1;i <= 5;i++){
printf("%d ",players[i]);
}
return 0;
}
勇敢的铠甲后人们快关注博主,与铠甲勇士们一起对抗蠢蠢欲动的异能兽吧!