【赛时总结】 ◇赛时·IV◇ CODE FESTIVAL 2017 Final

◇赛时-IV◇ CODE FESTIVAL 2017 Final


□唠叨□


①……浓浓的 Festival 气氛
②看到这个比赛比较特别,我就看了一看……看到粉粉的界面突然开心,所以就做了一下 `(*∩_∩*)′
③没想到这是大佬才能做的比赛 QwQ
④我发现我读题读了20多分钟……


□题目&解析□

◇居然有水题◇A - AKIBA

  • 【Atcoder CF2017 Final A】
  • 【翻译】
    你得到了一个长度小于等于50的字符串S。
    高桥(某主人物)能够在这个字符串S的任何位置插入'A'任意多次,请问他是否能将S变为“AKIHABARA”。是输出YES,否则输出NO。
  • 【解析】
    对于这种字符串匹配问题,我们可以储存原字符串匹配到的位置i,和目标字符串匹配到的位置j。
    这道题有一种特殊判断——当目标串中有'A'未匹配时,可以忽略,因为高桥可以在那里插入一个'A'。判断掉这种特殊情况后,我们可以继续匹配,直到发现无法匹配,或者最后原串或者目标串没有匹配完,就说明匹配失败了。
    但是注意如果目标串末尾还有A没有匹配的话是算匹配成功的(在末尾一直加'A')。
  • 【源代码】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const string goal="AKIHABARA";
int main()
{
    string str;
    cin>>str;
    int len=str.length();
    bool right=true;
    int i=0,j=0;
    for(;i<len && j<9;)
    {
        if(str[i]==goal[j]) {i++,j++;continue;}
        if(goal[j]=='A') {j++;continue;}
        right=false;
        break;
    }
    while(j<9 && goal[j]=='A') j++;
    if(i<len || j<9) right=false;
    printf("%s\n",right? "YES":"NO");
    return 0;
}

◇找规律◇ B - Palindrome-phobia

  • 【Atcoder CF2017 Final B】
  • 【翻译】
    Snuke有一个只包含 'a','b','c' 的字符串S。
    但是他有“回文恐惧症”,他想要改变一下字符串S中一些字母的顺序,使得S中不包含任何一个长度超过(大于)1的回文串。判断这是否可能。
  • 【解析】
    说实话这道题我是自创了一大堆数据然后暴力找的规律……
    也没有什么特别严格的证明(希望dalao们能帮我解释一下为什么下面这个规律是对的),规律就是下面:

    字符串中出现最多的字母的次数不能比其他两个字母各自出现的次数大超过1
    例:a出现3次,b出现2次,c出现1次,3-2≤1,但是 3-1 > 1 ,所以是不行的

因此先统计一遍a~c出现的次数存入tot[],再对tot[]排序,判断上述规律是否成立。

  • 【源代码】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int main()
{
    string str;
    cin>>str;
    int len=str.length(),tot[3]={};
    for(int i=0;i<len;i++)
        tot[str[i]-'a']++;
    sort(tot,tot+3);
    if(tot[2]-tot[0]>1 || tot[2]-tot[1]>1) printf("NO\n");
    else printf("YES\n");
    return 0;
}

◇大暴力◇ C - Time Gap

  • 【Atcoder CF2017 Final C】
  • 【翻译】
    来自世界各地的 N+1 名选手参加了 Code Festifal XXXX ,包括 Takahashi。
    Takahashi 调查并计算出第i名选手所在城市与他自己所在城市的时差_i。时差如下定义:对于城市A和城市B,当A为0点时,B为b点,此时时差为 min(b,24-b)(24小时制)。例如,当 Takahashi 所在城市为0点时,第i名选手所在城市的时间要么是 D_i,要么是 24-D_i。
    记S为 Takahashi 所在城市为0点时,每两个城市间的时差的最小值。
    求出尽可能大的S。
  • 【解析】
    输入后先把 Takahashi 所在城市为0点加上。(至于为什么……看第三组样例)
    然后特判一下٩(๑>◡<๑)۶ :当城市数量超过24个时,也就包含了0~23时所有的时间,且有两个城市时间相同(抽屉原理,共24个整点,当城市数量超过24个时,必有两个城市时间相同)。因此这种情况答案为0。
    对于每个城市有2个时间可取,因为要使最小值最大,所以就不能使两个城市的时间相等。很容易想到搜索大暴力(因为当N+1>24的情况已经特判了,所以N≤24时,时间复杂度就特别低)。
    用bool数组 u[] 记录已经决策过的城市的时间,避免重复!然后每次判断 D_i 在 u[] 中是否存在,不存在就在 u[] 中标记,并进行下一个城市的决策,返回后回溯。同样,对于 24-D_i 也进行此类操作,但是注意当 D_i=12 时 D_i=24-D_i ,会重复,应排除。
    最后统计答案。记得将答案储存变量初始化为0,因为当必然有两个城市时间相同时,无法得到期望的答案,在搜索完毕时并没有对答案进行更新,这就会导致最后输出的答案出问题。但是这种情况答案总是为0,所以将答案变量初始化为0是很聪明的做法。
  • 【源代码】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXN 50
int n,t[MAXN+5],ans=0;
bool u[25];
void dfs(int x)
{
    if(x==n)
    {
        int Min=1e8,last=0;
        for(int i=1;i<24;i++)
            if(u[i])
            {
                Min=min(Min,i-last);
                last=i;
            }
        Min=min(Min,24-last);
        ans=max(ans,Min);
        return;
    }
    if(!u[t[x]])
        {u[t[x]]=true;dfs(x+1);u[t[x]]=false;}
    if(t[x]!=(24-t[x])%24 && !u[24-t[x]])
        {u[24-t[x]]=true;dfs(x+1);u[24-t[x]]=false;}
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&t[i]);
    t[n++]=0;
    if(n>24) {printf("0\n");return 0;}
    dfs(0);
    printf("%d\n",ans);
    return 0;
}

woc 后面不会做了 ( ̄へ ̄)

The End

Thanks for reading!

- Lucky_Glass

猜你喜欢

转载自www.cnblogs.com/LuckyGlass-blog/p/9285912.html