银河出逃时 2021-07-12 09:17 采纳率: 88.2%
浏览 60
已结题

Python,一道,题,马上比赛了!

马上比赛了!
描述

周末程老板催黄同学和刘同学出门运动。但因为他俩太卷了,于是他们决定在纸上模拟爬山。
纸上有个从左到右的排列p。首先黄同学选择一个数x并把这个数告诉刘同学。之后,刘同学选择一个不同的数y。(1≤x≤n,1≤y≤n,x≠y)
接着两人的游戏按照如下方式轮流进行,黄同学先手:
如果是黄同学的轮次,黄同学需要把当前自己的数x改成x’,满足
1≤x′≤n,∣x′−x∣=1,x′≠y,px′<px
2.如果是刘同学的轮次,刘同学需要把当前自己的数y改成y’,满足
1≤y′≤n,∣y′−y∣=1,y′≠ x,py′<py
如果谁不能动,谁就输了,另一个人赢。你作为黄同学的粉丝,想知道有多少个初始的x,使得两人在最优策略下黄同学能赢。

输入格式
输入有两行,第一行一个整数n,(2≤n≤10000),代表排列的长度。
第二行n个整数,代表排列p。
输出格式
输出一个整数,代表有多少个初始的x,使得黄同学能赢
输入样例
5
1 2 5 4 3
输出样例
1
数据规模
对于20%数据,2≤n≤500
对于50%数据,2≤n≤2000
对于100%数据,2≤n≤100000

帮我看代码哪里错了,请给出正解
谢!


n = int(input('请输入一个整数:'))
num = input('请输入%d个整数,以空格隔开:' % int(n)).split(' ')
p = list(map(int,num))
res = []
def climb():
    for i in range(len(p)-1):
        if p[i] > p[i+1]:
            if p[i] != max(p):
                res.append(p[i])
    return len(res)
print(climb())

  • 写回答

1条回答 默认 最新

  • 八云黧 2021-07-17 17:18
    关注

    我看到你在思否上的提问了,别人回答得很好了,把我想说的甚至我想吐槽的基本都写到了(就是这个毫无卵用的n和明明是下山偏偏叫爬山的问题),但是他是假设p中没有重复的数字,也就是没有考虑顶不为点而是一条线的情况,我就补充一下吧。

    对于一组形如[7 5 6 8 9 4 5 7 7 7 6 3 3 3 8]的数据,我们可以把每一个使数据排列从【降序、相等、升序】中发生变化的转折点称为顶,在该数据中为[7 5 6],7和5,[8 9 4]的4,[5 7 7]中的第一个7,[7 7 6]中第二个7,[6 3 3]中的第一个3,[3 3 8]中的第二个3和8。这些数字都是数据的顶,而顶之间的数字我们可以称之为坡。首先,根据游戏规则,如果先手落在一个坡数上(即一组有序数据的非两端处),那么只要后手落在这个坡数的降序一侧第一个数(可能是顶也可能是坡),那么先手下一步就没有移动空间了(因为要求∣x′−x∣=1说明只能左右移动一个数,x′≠y说明不能移动到降序侧的y,所以,只能移动到升序侧,则px'>px,与规则不符),所以可以知道,两人在最优策略下,先手下在坡上必输。

    现在考虑顶。这里我们引入坡长这个概念,一个顶的一侧坡的坡长为该坡中比顶小的数字的个数,或者是比顶大的数字个数的相反数。举两个例子,对[7 5 6]中的顶7,左坡长为0,右坡长为1。对于[7 5 6 8 9 4]中的顶5而言,左坡长为-1,右坡长-3。因为移动要满足px′<px的条件,对于坡长为0或负数的顶而言,不能从该顶向这个坡移动。对于两个坡长都为非正数的顶,下在该顶处将直接无法移动。而对于一边坡长为正,一边坡长非负数的顶而言,非负数一侧无法移动,所以下在该顶处和上面分析的下在一个坡点处完全相同。所以我们得到结论,想要赢,必须至少下在一个两坡长都为正数的顶处。

    对于坡长不相等的顶来说,假设该顶的左坡长为m,右坡长为n,(这里假设m<n,n<m的结论完全一样,是对称关系),如果当先手下在该顶处,后手直接落在右坡第一个位置。我们可以注意到,此时坡长即为可以移动的轮次,因为m<=n-1,所以先手一定会先不能移动,相等时由于处于先手,也是先卡死在坡底导致输掉。而对于坡长相等的顶来说(m=n),必有m>n-1,当先手移动m次后,后手会无法移动输掉比赛。所以我们得到结论,想要赢,必须至少下在一个两坡长都为相等正数的顶处。

    考虑先手下在左右坡长为n的顶上,如果此时有任意一个顶的任意一侧坡长为m>=n,只要后手下在这个顶上,后手的移动次数就不少于先手,当先手用完次数就会先无法移动从而输掉游戏。所以我们得出最终结论,先手要赢,只能下在两坡长都为相等正数且该数必须为左右坡长的唯一最大值的顶处。

    所以有以下python代码

    n = int(input('请输入一个整数:'))
    num = input('请输入%d个整数,以空格隔开:' % int(n)).split(' ')
    p = list(map(int, num))
    # 这个数组用来储存小山顶的左坡长
    leftLenList = []
    # 这个数组用来储存小山顶的右坡长
    rightLenList = []
    # 由于python没有直接的枚举类型,这里就用字典变量来代替
    State = {
        'RISE': -1,
        'ZERO': 0,
        'FALL': 1,
    }
    
    
    def climb():
        # 可以认为数组左端点的处在坡长为0的坡上
        lastState = currentState = State['ZERO']
        LenCount = 1
        for i in range(len(p) - 1):
            currentState = State['RISE'] if p[i] < p[i + 1] else (
                State['ZERO'] if p[i] == p[i + 1] else State['FALL'])
            if currentState != lastState:
                leftLen = 0 if lastState == State['ZERO'] else (
                    LenCount if lastState == State['RISE'] else -LenCount)
                rightLen = 0 if lastState == State['ZERO'] else (
                    -LenCount if lastState == State['RISE'] else LenCount)
                leftLenList.append(leftLen)
                rightLenList.append(rightLen)
                LenCount = 1
                lastState = currentState
            else:
                LenCount += 1
        rightLenList.pop(0)
        # 处理数组右端点
        currentState = State['ZERO']
        if currentState != lastState:
            leftLen = LenCount if lastState == State['RISE'] else -LenCount
            rightLen = -LenCount if lastState == State['RISE'] else LenCount
            leftLenList.append(leftLen)
            rightLenList.append(rightLen)
        rightLenList.append(0)
        # 出于性能考虑,就不调用max,inidex和count函数了,而是自己写循环
        maxLen = 0
        maxIndex = []
        for i in range(len(leftLenList)):
            if leftLenList[i] >= rightLenList[i]:
                bigger = leftLenList[i]
            else:
                bigger = rightLenList[i]
    
            if bigger > maxLen:
                maxLen = bigger
                maxIndex = [i]
            elif bigger == maxLen:
                maxIndex.append(i)
        return 1 if len(maxIndex) == 1 and leftLen[maxIndex[0]] == rightLen[maxIndex[0]] else 0
    
    print(climb())
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 8月3日
  • 已采纳回答 7月26日
  • 修改了问题 7月17日
  • 修改了问题 7月17日
  • 展开全部

悬赏问题

  • ¥15 init i2c:2 freq:100000[MAIXPY]: find ov2640[MAIXPY]: find ov sensor是main文件哪里有问题吗
  • ¥15 运动想象脑电信号数据集.vhdr
  • ¥15 三因素重复测量数据R语句编写,不存在交互作用
  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景