CSDN 编程竞赛十九期题解

竞赛总览

CSDN 编程竞赛十九期:比赛详情 (csdn.net)

竞赛题解

题目1、幼稚班作业

幼稚园终于又有新的作业了。老师安排同学用发给同学的4根木棒拼接成一个三角形。当然按照正常的逻辑,如果不能拼接成三角形,必然要折断某个木棍来拼接三角形。可是懒惰的小艺当然不会费力了!如果拼接不成三角形小艺就会把它凭借成类似边长1 1 2的伪三角形。如果伪三角形都拼接不成那就不交作业!

懒得做了,考虑到输出只有0、1、-1三种,直接强行骗分。1有4个点,0和-1各3个点。可以考虑对两种答案骗分,然后直接输出第三种答案,这样只需骗6个点即可通过本题。当然了,这么做的话时间肯定会慢一些,不可能和直接做题消耗的时间一样多。

题目2、环形单向链表

给一个单向链表,若其中包含环,请完善EntryNodeOfLoop方法找出该链表的环的入口结点,否则,输出null。要求空间复杂度为O(1)。

看道题还以为挺简单的,找到一个环即可。

但是仔细看了一下描述发现并没有这么简单。这道题是本场竞赛最坑的题。

它涉及多个坑:

1、代码模板有些问题,给的int类型,无法输出null。于是果断放弃模板,自己从头写。

2、需要找出所有的环。本来一开始我用集合做的,这样可以快速找到一个环,后来发现需要找多个环,所以用集合不太行。

3、输出多个环的入口时,用换行符分隔,而不是空格。这道题一直卡在90%,后来发现好像是这里的问题,把空格换成了换行符,竟然通过了。

总得来说,消耗了差不多五十分钟的时间调试这道题,实在是太坑了。

题目3、影分身

已知字符串str。字符串str包含字符’x’,’y’。如果相邻的两个字符不同,消除两个字符,优先从左边进行消除。xyyx -> yx -> 空。

直接用模拟法完成本题。

首先输入字符串,然后进行替换。

如果字符串中相邻两个字符相同,就跳过。直到遇到不同的字符(xy或yx),进行替换。

完成替换之后,更新字符串,去掉被替换的字符。

以上操作为一轮,循环进行上述操作,直到不再发生替换为止。

以样例yyxxxyyxy为例。

第一轮:yyxxxyyxy -> y(yx)x(xy)(yx)y,即yxy。

第二轮:yxy -> (yx)y,最终变为y。

不过这题用模拟法很危险,很容易超时,本人就遇到了几次超时的情况,优化之后才通过。可以将字符串传参设置为传递指针或引用,不要直接传值,否则必定超时。

评论区老兄分享了一种统计的思路,效率更高。对应下面这段代码:

#include 
#include 
#include 

int data [256];

int main () {
    std::string str;
    std::cin >> str;
    for (int i = 0; i < str.length (); i++) {
        data [str [i]] += 1;
    }
    int t = data ['x'] - data ['y'];
    char x = t > 0 ? 'x' : 'y';
    t = t > 0 ? t : -t;
    for (int i = 0; i < t; i++);
    return 0;
}

题目4、醉酒的狱卒

某监狱有一个由n个牢房组成的大厅,每个牢房紧挨着。每个牢房里都有一个囚犯,每个牢房都是锁着的。一天晚上,狱卒感到无聊,决定玩一个游戏。在第一轮,他喝了一杯威士忌,然后跑下大厅,打开每个牢房的锁。在第二轮比赛中,他喝了一杯威士忌,然后跑下大厅,锁上每隔一个的牢房的锁(牢房2、4、6....)。在第三轮比赛中,他喝了一杯威士忌,然后跑下大厅。他每隔三个牢房(第3、6、9号牢房)就去一次。如果牢房被锁上了,他就把它打开;如果牢房门打开了,他就锁上牢房。他重复n轮,喝最后一杯,然后昏倒。一些囚犯意识到他们的牢房被解锁且狱卒丧失了行动能力。他们就可以立即逃跑。现在根据牢房数量,确定有多少囚犯越狱。

从题目描述中可以发现,1号房间的门在第一回合会被打开,并且之后不会再被访问,所以1号房间的人必然可以出去。

其余房间在第一回合也会被解锁,我们只需统计从第二回合开始的房间访问次数即可。如果房间从第二回合开始被访问了偶数次,那么其加锁和解锁状态会被相互抵消。由于房间在第一回合完成之后已经被解锁,所以如果之后再访问偶数次使得加锁和解锁状态抵消的话,房间中的人必然可以出去。

#include 

int n;

int match (int x) {
    int tot = 0;
    for (int i = 2; i <= n; i++) if (x % i == 0) tot = tot + 1;
    return tot;
}

int main () {
    int t;
    scanf ("%d", &t);
    while (t --> 0) {
        int x = 1;
        scanf ("%d", &n);
        for (int i = 2; i <= n; i++) if (match (i) % 2 == 0) x = x + 1;
    }
    return 0;
}

需要注意的是,本题一次测试有多组输入,样例中也是这么写得。

使用上述代码中的match函数来统计每一个房间被访问的次数。

第一个房间不需要计算,房间中的人肯定可以出去,所以设置初始值 x = 1。

在第一回合之后,从第二个房间开始,如果房间被访问了偶数次,那么房间中的人就可以出去(x = x + 1)。

你可能感兴趣的:(CSDN,竞赛题解,算法,c++)