6. 2023년 12월 GESP Python 레벨 6 프로그래밍 질문
[레벨 6 프로그래밍 질문 1]
[시험문제명] : 레벨 깨기 게임
제한시간 : 2.0초
메모리 제한 : 128.0MB
【 문제 설명】
당신은 레벨을 깨는 게임에 도착했습니다.
이 게임은 총 N 개의 레벨로 구성되어 있으며, 각 레벨에는 M개의 채널이 있으며, 채널을 선택하고 다음 레벨로 이동해야 합니다. 그 중 i- 번째 채널을 이용하면 ai 레벨 로 올라갈 수 있는데 , 즉 현재 x 레벨에 있다면 i- 번째 채널을 선택하면 곧바로 x + ai 레벨로 올라오게 된다 (특히, x + ai ≥ N 이면 레벨을 통과합니다. 또한 레벨 S를 성공적으로 종료하면 bs 포인트 도 얻을 수 있습니다 .
게임이 시작되면 레벨 0 이 됩니다 . 레벨 클리어 시 얻을 수 있는 최대 총점은 얼마인지 알려주세요.
[ 설명 입력]
첫 번째 줄의 두 정수 M 과 N 은 각각 각 레벨의 레벨 수와 채널 수를 나타냅니다.
다음 줄에는 단일 공백으로 구분된 M 개의 정수 a 0 , a 1,…, aM -1 이 포함됩니다 . 1 ≤ ai ≤ N 이 보장됩니다 .
다음 줄에는 단일 공백으로 구분된 N 개의 정수 b 0 , b 1,…, bM -1 이 포함됩니다 . 보장 | bi | ≤ 10⁵ .
[ 출력 설명]
한 줄에 하나의 정수로, 레벨을 통과할 때 얻을 수 있는 최대 점수를 나타냅니다.
【데이터 규모】
테스트 포인트의 20% 에 대해 M =1 이 보장됩니다 .
테스트 포인트의 40% 에 대해 N ≤ 20 이 보장되고 M ≤ 2 가 보장됩니다 .
모든 테스트 포인트에 대해 N ≤ 10⁴ 이 보장 되고 M ≤ 100 이 보장됩니다 .
【분석】
방법 1
" 재귀적 " 알고리즘을 사용하여 레벨 0 부터 가장 높은 점수를 가진 레벨까지 각 채널을 선택합니다 ( 0 점 및 음수 정렬 채널 방지 ) . 각 레벨에서 각 채널을 선택하고 점수가 기존 값보다 크면 업데이트합니다.
시간 복잡도: O ( NM ) , 10⁴ ×100≤ 10⁶ , 시간 초과 없음.
【완전한 코드】
n, m = [int(i) for i in input().split()]
a = [int(i) for i in input().split()]
b = [int(i) for i in input().split()]
dp = [0] * (n + 1) # 到第i关获得的最高得分
for i in range(n):
for j in range(m):
t = min(i + a[j], n) # 最高通关数为第n关
if dp[t] == 0:
dp[t] = dp[i] + b[i]
else:
dp[t] = max(dp[t], dp[i] + b[i]) # 考虑有负值的情况,取大者
print(dp[n])
【작업 결과】
방법 2
레벨 0을 통과하면 1 점 의 가치가 있습니다 . (b[0]) 각 레벨을 " 횡단 " 하고 각 채널을 " 횡단 " 합니다. 이전 레벨에 클리어한 점수가 있는 경우 해당 레벨의 점수와 해당 점수로 계산됩니다. 최대값이 사용됩니다 ( 0 점을 피하기 위해 음수 정렬 채널 ) .
시간 복잡도: O ( NM ) , 10⁴ ×100≤ 10⁶ , 시간 초과 없음.
【완전한 코드】
n, m = [int(i) for i in input().split()]
a = [int(i) for i in input().split()]
b = [int(i) for i in input().split()]
f = [b[0]] # 添加第0关分
for i in range(1, n):
f.append(0) # 本关初始0分
for pway in a:
if i - pway >= 0 and f[i - pway]: # 上一关存在并有分值
# 本站已有分值时,取本站与上一站分中大者,否则取上一站分
f[i] = max(f[i], f[i - pway]) if f[i] else f[i - pway]
if f[i]: # 本关通过加b[i],负分不加
f[i] += max(0, b[i]) # 负分通道不走(避免进入负分关)
print(f[i])
【작업 결과】
[레벨 6 프로그래밍 문제 2 ]
[시험문제명] : 업무소통
시간 제한: 2.0초
메모리 제한: 128.0MB
【 문제 설명】
회사에는 0 부터 N -1 까지 번호가 매겨진 N명의 직원이 있습니다 . 그 중 상사인 0 번 사원을 제외한 모든 사원에게는 직속 상사가 있습니다. i 번 직원의 직속 상사 가 fi 라고 가정합니다 .
회사는 엄격한 관리 시스템을 갖추고 있으며 각 직원은 직접 또는 간접적인 리더십에 의해서만 관리될 수 있습니다. 특히 x = y 또는 x = fy 또는 x가 fy 를 관리할 수 있는 경우에만 직원 x가 직원 y 를 관리할 수 있다고 규정되어 있습니다 . 특히 0 번 사원의 상사는 자신만 관리할 수 있고 다른 직원은 관리할 수 없습니다.
이제 일부 동료가 협업을 원하고, 협업을 진행해 줄 동료를 찾고 싶은데, 이 동료는 협업에 참여하는 모든 동료를 관리할 수 있어야 합니다. 이 조건을 충족하는 직원이 여러 명이라면 가장 높은 숫자를 가진 직원을 찾으려고 합니다. 그들을 도울 수 있나요?
[ 설명 입력]
첫 번째 줄에는 직원 수를 나타내는 정수 N 이 포함됩니다.
두 번째 줄에는 공백으로 구분된 N 개의 양의 정수( f 1 , f 2 ,…, fN -1 )가 포함되어 있습니다 .
세 번째 줄에는 정수 Q 가 포함되어 있으며, 이는 정리해야 할 Q 개의 경우가 있음을 나타냅니다 .
다음은 Q 라인이며 각 라인은 협력을 설명합니다. 시작은 이 협력에 참여하는 직원 수를 나타내는 정수 m (2 ≤ m ≤ N ) 이고 그 뒤에는 참여하는 직원 수를 나타내는 m 정수가 옵니다. 이 협력 ( 번호가 합법적이고 반복되지 않는지 확인 ) .
회사 구조가 합법적인지 확인하십시오. 즉, 직간접적인 리더인 직원이 없는지 확인하십시오.
[ 출력 설명]
출력 Q 라인, 각 라인에는 각 협력의 호스트에 대해 차례로 선택되는 정수가 있습니다.
【 데이터 규모 】
테스트 포인트의 50% 에 대해 N ≤ 50 이 보장됩니다 .
모든 테스트 포인트에 대해 3≤ N ≤300 , Q ≤100 이 보장됩니다 .
【분석】
방법 1
먼저 레이어별 상향 ( 재귀 ) 방식을 사용하여 각 개인의 모든 리더를 찾아 2차원 목록에 표시하고 , 각 팀별로 가장 높은 숫자를 가진 공통 리더를 하나씩 찾습니다. 답변.
시간 복잡도: O ( QNM ) ≤ O ( QN ²) , 100 × 300² ≤ 9 × 10⁶©107 , 시간 초과 없음.
【완전한 코드】
n = int(input())
mngr = [[] for i in range(n)] # 不能用[[]]*n
for k in [(i,int(j)) for i,j in enumerate(input().split())]:
mngr[k[1]].append(k[0]+1)
rel = [[0] * n for i in range(n)] # “行”为领导编号,“列”为员工编号
def dfs(row,col):
rel[row][col] = 1 # 存在领导关系则为1, 否则是0
for c in mngr[col]:
dfs(row,c)
for i in range(n): # 建每个人的所有领导关系(直接、间接)表
dfs(i,i)
q = int(input())
for _ in range(q):
x = [int(i) for i in input().split()][1:] # 第1个是人数本处用不上,丢弃
ans = -1
for r in range(n):
for y in x:
if not rel[r][y]: # 每位员工r都是领导,则不会break
break
else:
ans = r
print(ans)
【작업 결과】
방법 2
먼저, 각 개인의 직접 리더십과 간접 리더십을 단계별로 활용하여 2차원 목록으로 표시하고 , 각 팀별로 가장 높은 숫자를 가진 공통 리더를 하나씩 찾아내는 것이 답이다.
시간 복잡도: O ( QMN ) ≤ O ( QN² ) , 100 × 300² ≤ 9 × 10⁶©107 , 시간 초과 없음.
【완전한 코드】
n = int(input())
b = [[0] * n for i in range(n)]
f = [0]+[int(i) for i in input().split()] # 直接领导关系
for i in range(n): # 间接领导关系b[i][j]为1表示i是j的领导
b[i][i] = 1 # 自己可以管自己
b[0][i] = 1 # 老板管所有员工
sup = f[i] # 找直接领导
while sup: # 领导不是老板就继续找
b[sup][i] = 1;
sup = f[sup] # 找间接领导(领导的领导)
q = int(input())
for _ in range(q):
a = [int(i) for i in input().split()] # 第1个a[0]是人数, 每次合作的员工列表
for i in range(2, a[0]+1): # 从第2个员工开始找与前面员工的共同领导
for j in range(min(a[i], a[i - 1]), -1, -1): # 从编号最小的开始
if b[j][a[i]] and b[j][a[i - 1]]: # 如果是共同领导
a[i] = j # 当前员工换成共同领导
break
print(a[a[0]])
【작업 결과】