“ Python也太香了2.0。”
"题解仅供参考。"
CCF-CSP认证地址:http://cspro.org/
声明:这里的202006-2稀疏向量这道题,找遍了CSDN都没有找到超过60分的Python答案,如果有,可以dd我哈哈,思路很简单,代码是没错的,但最后的测试数据量太大了。
先上一波运行结果
01
—
总结
第二题的坑非常多,稍微没考虑到就扣你个四五十的,到时候CSP证都没得拿了。
写的时候要把题目啃多两遍再写,千万不要看到题目感觉懂了就开始写。
很多时候显示错误,但就是不知道哪里错了,很痛苦,一定要善于使用debug。
按照CSP真题顺序贴代码
稀疏向量
—
def index(): lineOne = [int(item) for item in input().split()] size1 = lineOne[1] size2 = lineOne[2] s = 0 v1 = {} v2 = {} for i in range(size1): ls = [int(item) for item in input().split()] v1[ls[0]] = ls[1] for i in range(size2): ls = [int(item) for item in input().split()] v2[ls[0]] = ls[1] v = v1.keys() & v2.keys() for item in v: s += v1[item] * v2[item] print(s)index()
回收站选址
—
def index(): size = int(input()) zbList = [] levelList = [0 for i in range(5)] for i in range(size): ls = [int(item) for item in input().split()] zbList.append([ls[0], ls[1]]) for zb in zbList: if is0(zbList, zb[0], zb[1]) == True: level = getLevel(zbList, zb[0], zb[1]) levelList[level] += 1 for lv in levelList: print(lv)# 判断是不是0级站点 (上下左右都要有站点)# return True | Falsedef is0(zbList, x, y): if [x + 1, y] in zbList and [x - 1, y] in zbList and [x, y + 1] in zbList and [x, y - 1] in zbList: return True else: return False# 获取站点的等级# return level(int)def getLevel(zbList, x, y): level = 0 if [x + 1, y + 1] in zbList: level += 1 if [x + 1, y - 1] in zbList: level += 1 if [x - 1, y + 1] in zbList: level += 1 if [x - 1, y - 1] in zbList: level += 1 return levelindex()
小明种苹果(续)
—
def index(): TreeSize = int(input()) delAppleList = [] dropList = [0 for item in range(TreeSize)] # 记录下掉落苹果的树 T, D, E = 0, 0, 0 for i in range(TreeSize): ls = list(map(int, input().split())) delAppleList.append(ls[1:]) for i, item in enumerate(delAppleList): appleNum = item[0] for j in range(1, len(item)): if item[j] <= 0: appleNum += item[j] elif appleNum != item[j]: # 防止同一颗树掉落两次时 掉落苹果的树的总数增加 (小细节) if dropList[i] != 1: dropList[i] = 1 D += 1 appleNum = item[j] T += appleNum if D >= 3: for i in range(len(dropList)): prevTree = i - 1 nextTree = i + 1 curTree = i if nextTree > len(dropList) - 1: nextTree = 0 if dropList[prevTree] == dropList[curTree] == dropList[nextTree] == 1: E += 1 print(T, D, E)index()
二十四点
—
def index(): n = int(input()) retList = [] for i in range(n): num = eval(input().replace("x", "*").replace("/", "//")) if num == 24: retList.append("Yes") else: retList.append("No") for ret in retList: print(ret)index()
小明放学
—
def index(): light = [int(item) for item in input().split()] # 一轮红绿灯的时间 oneTime = sum(light) # 红黄绿灯的时间 timeDic = dict(zip([1, 2, 3], light)) # 红黄绿灯的下一个灯是什么灯 lightDic = dict(zip([1, 2, 3], [3, 1, 2])) n = int(input()) lightList = [] for i in range(n): ls = [int(item) for item in input().split()] lightList.append(ls) s = 0 for item in lightList: if item[0] == 0: s += item[1] else: # 计算此时是什么灯 time = s % oneTime while time > item[1]: time -= item[1] # 更新灯颜色 item[0] = lightDic[item[0]] # 更新秒数 item[1] = timeDic[item[0]] item[1] -= time if item[0] == 1: s += item[1] elif item[0] == 2: s += item[1] + timeDic[lightDic[item[0]]] print(s)index()
买菜
—
def index(): n = int(input()) H = [] W = [] # H的装车时间 for i in range(n): ls = [int(item) for item in input().split()] for i in range(ls[0], ls[1]): H.append(i) # W的装车时间 for i in range(n): ls = [int(item) for item in input().split()] for i in range(ls[0], ls[1]): W.append(i) # 找出子集 sameTimeList = list(set(H).intersection(set(W))) print(len(sameTimeList))index()
碰撞的小球
—
class ball: def __init__(self, direction, maxDir): self.direction = direction # 小球初始位置 self.flag = 1 # 1 向右走 -1 向左走 self.maxDir = maxDir # 边界 def go(self): self.direction += self.flag def changeDir(self): self.flag = -self.flag def getDir(self): return self.direction# 判断两个小球是否碰撞def isCollision(ball1, ball2): return ball1.getDir() == ball2.getDir()# 判断小球是否到达边缘def isMax(ball): return ball.getDir() == ball.maxDir or ball.getDir() == 0def index(): lineOne = [int(item) for item in input().split()] maxDir = lineOne[1] time = lineOne[2] ballDirList = [int(item) for item in input().split()] ballList = [] # 创建 若干个小球 for item in ballDirList: b = ball(item, maxDir) ballList.append(b) # 开始运动 一共运动time秒 for i in range(time): # 所有小球前进 1 步 for b in ballList: b.go() # 判断小球是否到达边缘 for b in ballList: if isMax(b): b.changeDir() # 判断两个小球是否碰撞 for i1 in range(len(ballList)): for i2 in range(i1, len(ballList)): if ballList[i1] != ballList[i2]: if isCollision(ballList[i1], ballList[i2]): ballList[i1].changeDir() ballList[i2].changeDir() for b in ballList: print("%d " % b.getDir(), end=" ")index()
游戏
—
def index(): def is2(num, k): return num % k == 0 or (num - k) % 10 == 0 lineOne = [int(item) for item in input().split()] childSum = lineOne[0] # 小朋友总数 k = lineOne[1] # 报到k的倍数或最后一个数为k的小朋友淘汰 childList = [i + 1 for i in range(childSum)] # 创建一群小朋友并从1开始赋予编号 num = 1 # 小朋友报到的数 # 如果剩下的小朋友数量 > 1 就一直报数 while len(childList) > 1: # 从数组中弹出数组中的第一个小朋友 child = childList.pop(0) # 如果这个小朋友报的数不满足淘汰条件 if is2(num, k) == False: # 把小朋友重新放到数组的最后一个 进行下一轮报数 childList.append(child) num += 1 # 执行到这说明小朋友数组里已经只剩1个小朋友 输出这个最后胜利的小朋友 print(childList[0])index()
公共钥匙盒
—
def index(): N, K = map(int, input().split()) keyList = [i + 1 for i in range(N)] # 默认钥匙盒 borrowList = [] # 借出记录 for i in range(K): w, s, c = map(int, input().split()) borrowList.append((w, s, s + c)) # s+c表示归还时间 timeList = [] for item in borrowList: timeList.append((item[0], item[1], 1)) # 借的时间点 0 钥匙编号 1 借还时间 2 (1表示借) timeList.append((item[0], item[2], 0)) # 还的时间点 0 钥匙编号 1 借还时间 2 (0表示还) # 优先按照借还时间点排序 # 如果借的时间点 == 还的时间点,优先让还排在前面 # 如果同一时间有多把钥匙还,则优先让编号小的排在前面 timeList = sorted(timeList, key=lambda item: (item[1], item[2], item[0])) for item in timeList: if item[2] == 1: # 借 keyList[keyList.index(item[0])] = None elif item[2] == 0: keyList[keyList.index(None)] = item[0] for item in keyList: print(item, end=" ")index()
学生排队
—
def index(): stuSum = int(input()) changeSum = int(input()) stuList = [i + 1 for i in range(stuSum)] changeList = [] for i in range(changeSum): ls = [int(item) for item in input().split()] changeList.append(ls) for c in changeList: index = stuList.index(c[0]) stuList.remove(c[0]) stuList.insert(index + c[1], c[0]) for stu in stuList: print("%d" % stu, end=" ")index()
工资计算
—
def index(): n = int(input()) # 如果高于3500才开始判断 否则不需要交税 if n > 3500: # 税前收税点 prevMoney = [0, 1500, 4500, 9000, 35000, 55000, 80000] prevMoney = [item + 3500 for item in prevMoney] # 对应的税率 prevS = [0.03, 0.1, 0.2, 0.25, 0.3, 0.35, 0.45] # 税前收税点转化后的税后收税点 afterMoney = [] afterMoney.append(3500) # 按照 税前工资 + 税率 计算出税后收税点 # 每一个税点: 前一个税后税点的钱 + (第i个税前税点的钱 - 第i-1税前税点的钱) * 税率 for i in range(1, len(prevMoney)): afterMoney.append(int(afterMoney[i - 1] + (prevMoney[i] - prevMoney[i - 1]) * (1 - prevS[i - 1]))) # 初始化税后工资的段位为最后一个 position = len(prevMoney) # 找到n在税后工资里的段位 如果没有找到 则说明 n 在税前 > 80000 for i in range(len(afterMoney)): if n < afterMoney[i]: position = i break # 因为最高税率也就 0.45 所以 最高的税前价格 不会超过税后价格的两倍,这里的两倍其实是大了的 # 所以可得 afterMoney[position-1] < n < 2 * n # 将afterMoney[position-1]设为最小值 minMoney = prevMoney[position - 1] # 将2 * n 设为最大值 maxMoney = 2 * n # 因为题目说 税前工资是一个整百的数,所以可以每次遍历都+100 for money in range(minMoney, maxMoney, 100): # 这里的money模拟的是税前工资 需要把money进行运算 再而判断是否与税后工资一致 # (1) = (money - minMoney) * (1 - prevS[position - 1]) 在[position-1,position]区间需要交的税后工资 # (2) = afterMoney[position-1] 在[0,position-1]的税后工资 # 总税后工资 = [0,position-1] 的全部税后工资 + [position-1,position] 部分税后工资 # 总税后工资 = afterMoney[position - 1] + (money - minMoney) * (1 - prevS[position - 1]) if int((money - minMoney) * (1 - prevS[position - 1])) + afterMoney[position - 1] == n: print(money) break # 没有超过3500的工资不用交税 直接输出原工资 else: print(n)index()
火车购票
—
class Seat: # 创建一排座位 def __init__(self, startNum): self.seat = [i for i in range(startNum, startNum + 5)] def isFull(self): return len(self.seat) == 0 def getSeatNum(self): return len(self.seat) def buySeat(self, num): if len(self.seat) < num: return -1 else: return [self.seat.pop(0) for i in range(num)]def index(): n = int(input()) buyList = list(map(int, input().split())) if n > 20: n = 20 car = [] # 车厢 车厢包括 20排座位 retList = [] # 存储每次购买的位置 for i in range(n): s = Seat(i * 5 + 1) car.append(s) # 优先买相邻的座位,如果没有 则从第一节车厢遍历,有位置就买 for item in buyList: for s in car: if s.getSeatNum() >= item: retList.append(s.buySeat(item)) break # 如果找不到相邻的座位 else: ls = [] for s in car: buyNum = min(s.getSeatNum(), item) ls += s.buySeat(buyNum) item -= buyNum if item == 0: break retList.append(ls) for i1 in retList: for i2 in i1: print(i2, end=" ") print()index()
俄罗斯方块
—
def index(): # 俄罗斯方块盘 numList = [] # 即将添加的一块俄罗斯方块 addList = [] # 存储即将添加的俄罗斯方块的坐标 addZbList = [] for i in range(15): ls = list(map(int, input().split())) numList.append(ls) for i in range(4): ls = list(map(int, input().split())) addList.append(ls) # 俄罗斯方块将在期盼中的第column列出现 column = int(input()) # 在矩阵中 column-1 表示 第 column 列 column -= 1 # 获取即将添加的俄罗斯方块的坐标 for i in range(len(addList)): for j in range(len(addList[i])): if addList[i][j] == 1: addZbList.append([i, j]) # 根据纵坐标排序 找出addZbList中最左边的方块 addZbList = sorted(addZbList, key=lambda item: item[1]) # 以排序后的 最左边的方块为起点 整体横向移动column 这样俄罗斯方块才能在期盼的第column列出现 addZbList = [[item[0], item[1] + column] for item in addZbList] maxSize = -1 # 找到俄罗斯方块能下落到的最低点 for i in range(1, 15): for item in addZbList: # 如果没有到达底部 判断每个方块有没有触碰到 原来就存在的方块 if item[0] + i < 15: if numList[item[0] + i][item[1]] == 1: maxSize = i - 1 break # 如果到达了底部 else: maxSize = i - 1 # 如果找到了俄罗斯方块能下落到的最低点 if maxSize != -1: break # 把俄罗斯方块的坐标移到最低点 addZbList = [(item[0] + maxSize, item[1]) for item in addZbList] for item in addZbList: numList[item[0]][item[1]] = 1 for i1 in numList: for i2 in i1: print(i2, end=" ") print()index()
消除类游戏
—
def index(): column, row = list(map(int, input().split())) # 需要判断消除的矩阵 numList = [] for i in range(column): ls = list(map(int, input().split())) numList.append(ls) # 用于存储坐标 numSet = set() # 按行处理 for i, i1 in enumerate(numList): for j in range(1, row - 1): if i1[j - 1] == i1[j] == i1[j + 1]: numSet.add((i, j - 1)) numSet.add((i, j)) numSet.add((i, j + 1)) # 按列处理 for i in range(row): for j in range(1, column - 1): if numList[j - 1][i] == numList[j][i] == numList[j + 1][i]: numSet.add((j - 1, i)) numSet.add((j, i)) numSet.add((j + 1, i)) # 将numSet里的坐标在numList的对应位置消除(置为0) for item in numSet: numList[item[0]][item[1]] = 0 # 打印numList for i1 in numList: for i2 in i1: print(i2, end=" ") print()index()
日期计算
—
def isR(year): if year % 4 == 0 and year % 100 != 0: return True elif year % 400 == 0: return True else: return Falsedef getDay(day, r): m = 1 d = getDayByMon(m, r) while day > d: day -= d m += 1 d = getDayByMon(m, r) return (m, day)def getDayByMon(d, r): if d in [1, 3, 5, 7, 8, 10, 12]: return 31 elif d in [4, 6, 9, 11]: return 30 elif d == 2: if r: return 29 else: return 28def index(): y = int(input()) d = int(input()) MD = getDay(d, isR(y)) print(MD[0]) print(MD[1])index()
数字排序
—
def index(): n = int(input()) numList = list(map(int, input().split())) numDic = {} for num in numList: if num not in numDic: numDic[num] = 1 else: numDic[num] += 1 retList = sorted(numDic.items(), key=lambda item: (item[1], item[0])) retList.sort(key=lambda item: item[1], reverse=True) for item in retList: print(item[0], item[1])index()
画图
—
def index(): n = int(input()) zbList = [] for i in range(n): zbList.append(tuple(map(int, input().split()))) zbSet = set() for item in zbList: for i in range(item[0], item[2]): for j in range(item[1], item[3]): zbSet.add((i, j)) print(len(zbSet))index()
窗口
—
def index(): windowSize, touchSize = map(int, input().split()) windowList = [] # 窗口坐标列表 touchList = [] # 点击坐标列表 retList = [] # 最终结果列表 # 录入每个窗口坐标 for i in range(windowSize): t1 = tuple(map(int, input().split())) t2 = (i + 1,) t = t1 + t2 windowList.append(t) # 录入每个点击的点的坐标 for i in range(touchSize): touchList.append(tuple(map(int, input().split()))) for i in range(touchSize): windowNum = -1 window = None for j in range(windowSize): # (windowSize - 1 - j) 使得遍历的时候变成倒序遍历 # 如果鼠标点击的坐标在该窗口的范围内 if touchList[i][0] >= windowList[windowSize - 1 - j][0]: if touchList[i][0] <= windowList[windowSize - 1 - j][2]: if touchList[i][1] >= windowList[windowSize - 1 - j][1]: if touchList[i][1] <= windowList[windowSize - 1 - j][3]: # 记录被点击到的window window = windowList[windowSize - 1 - j] break # 如果遍历完windowNum还是-1 说明没有点击到窗口 if window == None: retList.append("IGNORED") else: # 否则将窗口放到列表的最后 注意:这里是从最后开始遍历 if len(windowList) > 1: windowList.remove(window) windowList.append(window) retList.append(window[4]) for item in retList: print(item)index()
ISBN号码
—
def index(): string = input() stringList = list(string.replace("-", "")) # 获取到最后一个字符 lastNum = stringList[-1] stringList = [int(item) for item in stringList[:len(stringList) - 1]] s = 0 for i in range(len(stringList)): s += stringList[i] * (i + 1) mod = s % 11 if mod == 10: if lastNum == "X": print("Right") else: string = list(string) string[-1] = "X" string = ''.join(string) print(string) else: if lastNum == str(mod): print("Right") else: string = list(string) string[-1] = str(mod) string = ''.join(string) print(string)index()
-END-
04
—
往期
Python版 CSP目前所有第一题