[2021.11.14]UPC-2021级新生个人训练赛第3场-19283 Problem E 调研

题目描述

有一直线型展台共有 m 个展位,按该展位离入口处的远近顺序编号,其编号分别为 1、2、……、m;其中只有 n 个是展示新技术的展位,最后一个展示新技术的展位编号为 m。
这次调研分两个小组进行,每个小组最多调研连续的 10 个展位,且每个小组调研的展位至少相隔 2 个展位。 
乐乐希望你设计一种安排方案,使领导调研更多的展示新技术的展位。

输入

第一行只有一个正整数:n,表示展示新技术的展位数 
第二行共有 n 个正整数,依次表示新技术展位的编号

输出

只有一行且只有一个正整数:领导调研过的不同的新技术展位数 

样例输入 Copy

5  
1 3 12 21 8

样例输出 Copy

5

提示

对于 30%的数据,  1 <= n <= m <= 10 
对于 70%的数据,  1 <= n <= m <= 1 000 
对于 100%的数据, 1 <= n <= m <= 1 00 000

题解:

题目其实并不困难,但所给的信息实在是太不充分了,而且还有很多特殊情况,所以过的人很少....尤其是要注意考虑当M很小的时候(M<=10)的时候。

调研的时候,两个小组是必须都要参与的(输入中的m应该满足条件m>=4,这样才可保证两个小组都有展台可以调研),所以当输入是

4
1 2 3 4  时

最终调研的新技术展台数量是 2 

其中小组A只调研了1号展台,而小组B因为要与小组A相隔两个展台,所以只调研了4号展台。

我的做法是..用数组a[i]储存第i号展台的情况,如果是新技术展台,其值为1,否则其值为0。

然后第一小组调研数量是不定的,因为第一小组每多调研一个展台,第二小组所调研的展台就要往后退一个,而第二小组所调研的展台数量不受限制,那么当然是越多越好~ 

先把代码贴出来 ; )

#include <cstdio>
#include <algorithm>
using namespace std;
int main(){
    bool a[100010]={false}; // a数组表示展台状况。
    int  b[100010];    //b数组是前缀和,表示从1~下标i 的所有新技术展台数量。
    int  c[100010];      //c数组的作用在下面:)
    int n,i,j,mx=0,s1=0,cnt=100011,len=0,mx1=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        scanf("%d",&j);
        if(j>len)len=j;     //   len储存的是展台数量
        a[j]=true;
    }
    b[1]=a[1];
    for(i=2;i<=len;i++){
        b[i]=b[i-1]+a[i];
    }
    for(i=1;i+3<=len;i++){    //c数组储存的是从第二小组调研的新技术展台数量,
        if(i+12<=len)               //下标i表示的是第一小组调研的最后一个展台
            c[i]=b[i+12]-b[i+2];  
        else
            c[i]=b[len]-b[i+2];    
    }
    for(i=1;i+3<=len;i++){    //i表示的是第一小组调研的起始展台
        for(j=i;j-i<=9&&j+3<=len;j++){     //j表示的是第一小组调研的结束展台
            s1+=a[j];
            if(s1>mx1) {               //mx1记录从1~j号展台中第一小组调研的新技术展台最大数。
                mx1 = s1;
                cnt = j;                //cnt用来记录第一小组调研新技术展台最多时的结束展台
            }
            if(j>=cnt)       //当第一小组调研结束展台大于等于调研新技术展台最多时的结束展台时
                if(mx<=mx1+c[j])    
                    mx=mx1+c[j];
            if(mx<s1+c[j])    //因为第一小组调研新技术展台最多时,并不代表两个小组总共调研最多
                mx=s1+c[j];    //所以重复判断了一次
        }
        s1=0;
    }
    printf("%d",mx);
    return 0;
}

时间复杂度大概是O(n)..吧?,好繁琐。

感觉方法应该可以更简洁一点,我的有些臃肿了....

如有纰漏,请多多指正!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值