赛码网输入输出总结+真题演练

前言

上次整理完在牛客网的输入输出之后,在赛码网却栽了根头。
因此今天再次整理下赛码网中的输入输出类型,并与在牛客网中的输入输出做对比。

类型一:测试组数不固定,每组三行数据

在这里插入图片描述
思路:如果遇到测试组数不固定的情况,则应该想到使用while True:命令。对于每组测试数据,都进行一次输出。如果知道了测试组数T,则使用代码行for i in range(T):

踩坑记录1

while True:
    n, m = map(int, input().split())
    a = [int(c) for c in input().split()]
    b = [int(d) for d in input().split()]
    c = list(set(a + b))
    c.sort()
    for i in range(len(c)):
        print(c[i])

:输出必须得用空格隔开。
修改后的代码:可输出正确答案。

while True:
    n, m = map(int, input().split())
    a = [int(c) for c in input().split()]
    b = [int(d) for d in input().split()]
    c = list(set(a + b))
    c.sort()
    for i in range(len(c)):
        print(c[i], end=' ')

踩坑记录2

还是上面的正确代码,我们来看下。
在这里插入图片描述
在这里插入图片描述
看到这里我也是震惊了。后面找官网解释说明,才发现人家确实已经早说好了,只是我们没有注意。
在这里插入图片描述
赛码网太恶心了。对于用惯了pycharm的用户来说是真的头痛。

类型2 测试组数不定,输入数据中有指定行数的多行输入(赛码网找老乡题最完美答案)

在这里插入图片描述

while True:
    N, M = map(int, input().split())
    a = []
    b = set()
    b.add(1)
    for _ in range(M):#将所有关系都添加到列表a中去
        a.append(list(map(int, input().split())))
    for i in range(M):#如果关系中的第一个元素或第二个元素存在于b中,则小赛的老乡找到了
        if (a[i][0] in b or a[i][1] in b) and a[i][2] == 1:
            b.add(a[i][0])
            b.add(a[i][1])
    print(len(b) - 1)

这是我自己写的代码。然鹅只有50%的通过率。

再看下最高赞正确答案:

while 1:
    N, M = map(int, input().split())
    res = []
    for i in range(M):
        a, b, c = map(int, input().split())
        if c == 1:
            r = [a, b] if a < b else [b, a]
            res.append(r)
    s = set()
    s.add(1)
    res.sort()
    for i in res:
        if i[0] in s:
            s.add(i[1])
    print(len(s) - 1)

对比了下我的答案和正确答案,想了半天就是想不出来我的为啥会只有50%的通过率。难道是因为要考虑边界条件吗?但是我也没发现正确答案里有考虑任何边界条件啊。醉了。
最后我试了一个测试用例:
5 3
1 4 1
2 4 1
3 4 1
答案输出应该是多少?明显是3吧。我的程序输出是3,标准答案输出是1。很明显,我的答案才是完全正确的!!!垃圾赛码网。

别急,到这里我终于又发现我的代码的问题了。我代码的问题在于,看个例子就知道了。
输入
5 3
2 4 1
1 4 1
2 3 1
答案该输出3的。我的代码只输出1。因为按顺序遍历时,我的代码跳过了第一组2和4的关系。
修改一下就好了

while True:
    N, M = map(int, input().split())
    a = []
    b = set()
    for _ in range(M):
        a = list(map(int, input().split()))
        if a[2] == 1:
            b.add(a[0])
            b.add(a[1])
    if 1 in b:
        print(len(b) - 1)
    else:
        print(0)

到这里,我的代码能解决所有的情况和问题。感觉该是最完美的答案了。不服来测

类型三:一组数据,有指定行数的多行输入,必须先将多行输入整合到一起的情况

京东笔试真题-终结者

在这里插入图片描述

n = int(input())
cor = []
for i in range(n):
    a, b = map(int, input().split())
    cor.append([a, a + b])

cor.sort(key=lambda x: x[1])  # cor中存储所有卡车的起始坐标和末尾坐标
start = cor[0][1]
count = 0  # 所需炮弹数量
ans = []  # 建立一个存放每颗炮弹干掉的卡车数量的列表
for res in cor:#贪心算法,参考leetcode引爆气球题
    if res[0] > start:
        start = res[1]
        ans.append(count)
        count = 1
    else:
        count += 1
ans.append(count)
ans.sort()
if len(ans) == 1:
    print(max(ans))
else:
    print(ans[-1] + ans[-2])

这是我的答案,利用贪心算法解决。然鹅通过率只有20%。
这里为什么要讲下这种类型呢,不是和第二种情况类似吗?
我在笔试时遇到的一个坑主要是,我将多行输入申请添加到一起时,它提示我使用for循环存放多行输入会引起内存超限???不知道有没有和我一样经历的?平时练习还好好的,一到笔试就这样,垃圾赛码网。
找bug要找到死。我这么一个完美的算法,竟然只有20的通过率。题目的答案区还没有python选项的答案。审题已经审了n遍了,也没发现问题。想不出来到底问题出在哪。杀了我算了。垃圾赛码网。
想到了再更吧,垃圾赛码网。
发布之后就想到了哪里错了。
在这里插入图片描述
找到了一位大神的思路,参考了下,找到了解决方法。链接: link.
所以我们修改下我们的代码。

n = int(input())
cor = []
for i in range(n):
    a, b = map(int, input().split())
    cor.append([a, a + b])
cor.sort(key=lambda x: x[1])  # cor中存储所有卡车的起始坐标和末尾坐标
ans = []  # 建立一个存放每颗炮弹干掉的卡车数量的列表
k = 0
while (k < n):#思路在于求出遍历所有卡车,单独发射一颗炮弹时能击穿的最大卡车数
    start = cor[k][1]
    count = 0
    for res in cor:
        if res[0] < start:
            count += 1
    ans.append(count)
    k += 1
ans.sort()
if len(ans) == 1:
    print(max(ans))
else:
    print(ans[-1] + ans[-2])

然鹅通过变为了0。后面一想就明白了,每颗炮弹能击穿的最大卡车数肯定是有重叠的。
那该怎么办呢?
思路转变为,先求出第一颗炮弹能击穿的最大卡车数,然后将这些卡车坐标移除,再求出第二课炮弹的能击穿的最大卡车数,这样就可以了。修改后的代码如下:

def fun(cor):  # 函数的作用是返回一颗炮弹能击穿的最大的卡车数量,并且返回炮弹坐标,炮弹坐标想一下就会明白
    k = 0
    max_num = 0
    ans = []
    while (k < len(cor)):
        start = cor[k][1]
        count = 0
        for res in cor:
            if res[0] <= start <= res[1]:
                count += 1
        if count > max_num:
            max_num = count
            ans = [max_num, start]  # ans1最后得到的值是一颗炮弹能击穿的最大卡车数,start为这颗炮弹的坐标
        k += 1
    return ans


n = int(input())
cor = []
for i in range(n):
    a, b = map(int, input().split())
    cor.append([a, a + b])
cor.sort(key=lambda x: x[1])  # cor中存储所有卡车的起始坐标和末尾坐标
ans1 = fun(cor)  # ans1=[max_num,start]max_num代表第一课炮弹能击穿的最大卡车数,start代表第一课炮弹的位置
cor2 = []
for res in cor:  # 将第一课炮弹所能击穿的最大卡车的数量中的卡车位置都移除,后面再次求第二颗炮弹能打穿的最大数量
    if res[0] > ans1[1] or res[1] < ans1[1]:
        cor2.append(res)  # 经过这步循环操作之后,cor中移除了第一课炮弹击穿的卡车的坐标
ans2 = fun(cor2)
print(ans1[0] + ans2[0])

经过这一步,通过率变为了70%。真是可喜可贺。自己太垃圾了。然而这样做,还是求得是局部最优值。
举个例子。
在这里插入图片描述
这种情况明显代码会输出5,然而实际是6.这说明垃圾贪心算法并不适用。老老实实暴力破解吧。
暴力思路:将每辆卡车的尾坐标视为一个炮弹位置。

def fun(cor, x1, x2):  # 函数的作用是返回两颗炮弹能击穿的最大的卡车数量
    count = 0
    for res in cor:
        if res[0] <= x1 <= res[1] or res[0] <= x2 <= res[1]:
            count += 1
    return count

n = int(input())
cor = []
cor2 = []
for i in range(n):
    a, b = map(int, input().split())
    cor.append([a, a + b])
    cor2.append(a + b)
cor.sort(key=lambda x: x[1])  # cor中存储所有卡车的起始坐标和末尾坐标
cor2.sort()
max_num = 0
for i in range(n):#两重循环遍历两颗炮弹的所有可能组合
    for j in range(i + 1, n):
        count = fun(cor, cor2[i], cor2[j])
        if count > max_num:
            max_num = count
print(max_num)

终于100AC通过了。
这道题也是醉了,开始以为用贪心,后面以为得放弃贪心用动态规划,最后发现是暴力解法。
部分参考代码来自赛码网,所有连接也已给出。如有异议联系本人修改或删除。

  • 12
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
赛马实验是一种常用的实验方法,用来测量和比较不同个体、组织或系统之间的性能。这个实验的基本原理是将不同条件下的参与者分为多组,然后观察和记录它们在相同环境下的表现和成果。 在赛马实验中,我们首先需要确定实验的目的和假设。然后根据假设,选择适当的参与者和参与者的特征进行分组。每组参与者都会在相同的环境条件下进行特定任务或活动,并被记录下来。 接下来,我们会设立一个合适的时间段,以确保实验的结果具有可比性。通过收集和分析数据,我们可以比较不同组参与者的表现和成果,评估哪种条件下的参与者更出色。 赛马实验可以被广泛应用于不同领域。例如,在医学研究中,赛马实验可以用来比较不同治疗方法对患者康复的效果。在教育领域,赛马实验可以用来评估不同教学方法对学生学习成绩的影响。在市场营销中,赛马实验可以用来比较不同广告策略对销售额的影响。 通过赛马实验,我们可以得出一些有意义的结论,以便进一步改进和优化现有的条件。然而,需要注意的是,赛马实验并不一定能够完全预测实际情况,因为实验环境和条件往往与现实世界存在差异。 总之,赛马实验是一种有效的实验方法,可以用来评估和比较不同条件下的参与者的表现和成果。通过这种实验,我们可以获得有关不同条件下的相对优劣的信息,并为进一步优化和改进提供有价值的参考。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值