서버에 요청을 보내는 프로그램은 요청이 실패하면 잠깐 기다렸다가 다시 보낸다.
작업마다 첫 대기 시간 b, 최대 대기 시간 c, 최대 시도 횟수 a, 대기 예산 T와 결과 문자열 s가 주어진다.
s의 i번째 글자는 i번째 시도의 결과다.
S는 성공, F는 일시적 실패(다시 보낼 수 있음), X는 영구 실패(다시 보내지 않음)이다.
작업마다 처음에는 대기 시간 w = b이고, 지금까지 기다린 시간의 합 W = 0이다.
작업마다 아래 1~5를 되풀이한다.
1. 요청을 한 번 보낸다(첫 요청은 T와 상관없이 언제나 보낸다).
2. 결과가 S이면 "ok"로, X이면 "fatal"로 끝난다.
3. 결과가 F이고 지금까지 a번 보냈으면 "exhausted"로 끝난다.
4. 그렇지 않으면 w만큼 기다린다. 다만 W + w가 T보다 크면 기다리지 않고 "timeout"으로 끝난다(W + w가 T와 같으면 기다린다).
5. 기다린 뒤 W에 w를 더하고, w를 두 배로 늘리되 두 배가 c보다 크면 w = c로 한다. 그리고 1로 돌아간다.
첫 줄에 작업 수 q가 주어지고, 다음 q줄에 작업마다 b, c, a, T, s가 빈칸 하나씩을 사이에 두고 주어진다.
작업마다 한 줄에 끝난 상태(ok, fatal, exhausted, timeout 중 하나를 따옴표 없이), 요청을 보낸 횟수, W를 빈칸 하나씩 띄워 입력 차례대로 출력하라.
입력
1 ≤ q ≤ 1,000, 1 ≤ b ≤ c ≤ 2,000,000,000, 1 ≤ a ≤ s의 길이 ≤ 100, 0 ≤ T ≤ 10^12, s는 S·F·X로만 이루어짐
ok 3 300
exhausted 4 550
timeout 2 500
ok 1 0
fatal 2 10
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
'일단 한 번 보내고, 끝에서 다시 보낼지 묻는' 흐름이라 do-while이 딱 맞아요: C·C++·Java·C#·JS·TS do { … } while (status == null);. Python과 크레이콘에는 do-while이 없어서 while True: … break(크레이콘 동안 (참) … 그만;)로 '적어도 한 번'을 만들어요. 함정은 while (W + w <= T) { … }처럼 조건을 먼저 묻는 거예요. 그러면 예산이 첫 대기보다 작을 때(예시 넷째 줄 T = 0) 요청을 한 번도 보내지 않아요. 상한은 삼항 연산자 한 줄로: C 계열·JS·TS w = w * 2 > c ? c : w * 2;, 크레이콘도 같은 모양 대기 * 2 > 상한 ? 상한 : 대기 * 2, Python만 순서가 달라 c if w * 2 > c else w * 2예요. 겉보기엔 int로 충분해 보이지만 c가 20억까지라 w * 2는 40억이 될 수 있고, 기다린 합은 99 × 20억까지 커져요. C·C++ int는 넘치면 정의되지 않은 동작(대개 음수로 돌아감)이고, Java·C# int는 조용히 음수로 돌아가서 w * 2 > c가 거짓이 되고 대기 시간이 음수가 돼요. 그래서 C·C++ long long, Java·C# long으로 받아요. Python은 정수 크기에 제한이 없고, JS·TS·크레이콘은 double이라 2^53 안의 이 값들을 정확히 다뤄요. 3번(횟수)과 4번(예산)을 묻는 차례를 바꾸면 마지막 시도 뒤에 예산을 따져 "exhausted"가 "timeout"으로 바뀌어요.
Pythonmain.py · 31 줄
import syslines = sys.stdin.read().split("\n")q = int(lines[0])out = []for line in lines[1:q + 1]: b, c, a, t, s = line.split() c, a, t = int(c), int(a), int(t) wait = int(b) # 다음에 기다릴 시간 waited = 0 # 지금까지 기다린 시간의 합 tries = 0 # Python에는 do-while이 없다: while True로 들어가 끝에서 멈출지 정한다(첫 시도는 언제나 한다) while True: result = s[tries] tries += 1 if result == "S": status = "ok" break if result == "X": status = "fatal" break if tries == a: status = "exhausted" break if waited + wait > t: status = "timeout" break waited += wait wait = c if wait * 2 > c else wait * 2 out.append(f"{status} {tries} {waited}")print("\n".join(out))
JavaScriptmain.js · 28 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const q = Number(lines[0]);const out = [];for (let j = 1; j <= q; j++) { const [b, c, a, t, s] = lines[j].trim().split(/\s+/); const cap = Number(c); const maxTries = Number(a); const budget = Number(t); let wait = Number(b); // 다음에 기다릴 시간 let waited = 0; // 지금까지 기다린 시간의 합 let tries = 0; let status = null; // 첫 시도는 언제나 한다: 몸통을 먼저 돌고 끝에서 계속할지 묻는다 do { const result = s[tries]; tries++; if (result === "S") status = "ok"; else if (result === "X") status = "fatal"; else if (tries === maxTries) status = "exhausted"; else if (waited + wait > budget) status = "timeout"; else { waited += wait; wait = wait * 2 > cap ? cap : wait * 2; } } while (status === null); out.push(`${status} ${tries} ${waited}`);}console.log(out.join("\n"));
TypeScriptmain.ts · 29 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const q: number = Number(lines[0]);const out: string[] = [];for (let j = 1; j <= q; j++) { const [b, c, a, t, s] = lines[j].trim().split(/\s+/); const cap: number = Number(c); const maxTries: number = Number(a); const budget: number = Number(t); let wait: number = Number(b); // 다음에 기다릴 시간 let waited = 0; // 지금까지 기다린 시간의 합 let tries = 0; let status: string | null = null; // 첫 시도는 언제나 한다: 몸통을 먼저 돌고 끝에서 계속할지 묻는다 do { const result: string = s[tries]; tries++; if (result === "S") status = "ok"; else if (result === "X") status = "fatal"; else if (tries === maxTries) status = "exhausted"; else if (waited + wait > budget) status = "timeout"; else { waited += wait; wait = wait * 2 > cap ? cap : wait * 2; } } while (status === null); out.push(`${status} ${tries} ${waited}`);}console.log(out.join("\n"));
JavaMain.java · 37 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int q = Integer.parseInt(br.readLine().trim()); StringBuilder out = new StringBuilder(); for (int j = 0; j < q; j++) { String[] p = br.readLine().trim().split("\\s+"); long wait = Long.parseLong(p[0]); // 다음에 기다릴 시간(2배가 int를 넘을 수 있다) long cap = Long.parseLong(p[1]); int maxTries = Integer.parseInt(p[2]); long budget = Long.parseLong(p[3]); String s = p[4]; long waited = 0; // 지금까지 기다린 시간의 합 int tries = 0; String status = null; // 첫 시도는 언제나 한다: 몸통을 먼저 돌고 끝에서 계속할지 묻는다 do { char result = s.charAt(tries); tries++; if (result == 'S') status = "ok"; else if (result == 'X') status = "fatal"; else if (tries == maxTries) status = "exhausted"; else if (waited + wait > budget) status = "timeout"; else { waited += wait; wait = wait * 2 > cap ? cap : wait * 2; } } while (status == null); out.append(status).append(' ').append(tries).append(' ').append(waited).append('\n'); } System.out.print(out); }}
C#Main.cs · 40 줄
using System;using System.Text;class Program{ static void Main() { int q = int.Parse(Console.ReadLine().Trim()); var sb = new StringBuilder(); for (int j = 0; j < q; j++) { string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); long wait = long.Parse(p[0]); // 다음에 기다릴 시간(2배가 int를 넘을 수 있다) long cap = long.Parse(p[1]); int maxTries = int.Parse(p[2]); long budget = long.Parse(p[3]); string s = p[4]; long waited = 0; // 지금까지 기다린 시간의 합 int tries = 0; string? status = null; // 첫 시도는 언제나 한다: 몸통을 먼저 돌고 끝에서 계속할지 묻는다 do { char result = s[tries]; tries++; if (result == 'S') status = "ok"; else if (result == 'X') status = "fatal"; else if (tries == maxTries) status = "exhausted"; else if (waited + wait > budget) status = "timeout"; else { waited += wait; wait = wait * 2 > cap ? cap : wait * 2; } } while (status == null); sb.Append(status).Append(' ').Append(tries).Append(' ').Append(waited).Append('\n'); } Console.Write(sb); }}
C++main.cpp · 30 줄
#include <iostream>#include <string>int main() { int q; std::cin >> q; for (int j = 0; j < q; j++) { long long wait, cap, budget; // 2배가 int(약 21억)를 넘을 수 있다 int maxTries; std::string s; std::cin >> wait >> cap >> maxTries >> budget >> s; long long waited = 0; // 지금까지 기다린 시간의 합 int tries = 0; std::string status; // 첫 시도는 언제나 한다: 몸통을 먼저 돌고 끝에서 계속할지 묻는다 do { char result = s[tries]; tries++; if (result == 'S') status = "ok"; else if (result == 'X') status = "fatal"; else if (tries == maxTries) status = "exhausted"; else if (waited + wait > budget) status = "timeout"; else { waited += wait; wait = wait * 2 > cap ? cap : wait * 2; } } while (status.empty()); std::cout << status << ' ' << tries << ' ' << waited << '\n'; }}
Cmain.c · 30 줄
#include <stdio.h>int main(void) { int q; scanf("%d", &q); for (int j = 0; j < q; j++) { long long wait, cap, budget; /* 2배가 int(약 21억)를 넘을 수 있다 */ int max_tries; char s[128]; scanf("%lld %lld %d %lld %127s", &wait, &cap, &max_tries, &budget, s); long long waited = 0; /* 지금까지 기다린 시간의 합 */ int tries = 0; const char *status = NULL; /* 첫 시도는 언제나 한다: 몸통을 먼저 돌고 끝에서 계속할지 묻는다 */ do { char result = s[tries]; tries++; if (result == 'S') status = "ok"; else if (result == 'X') status = "fatal"; else if (tries == max_tries) status = "exhausted"; else if (waited + wait > budget) status = "timeout"; else { waited += wait; wait = wait * 2 > cap ? cap : wait * 2; } } while (status == NULL); printf("%s %d %lld\n", status, tries, waited); } return 0;}
Craykonmain.cray · 45 줄
q = 콘솔.줄읽기().수로변환();반복 (j = 0; j < q; j++){ p = 콘솔.줄읽기().공백제거().나누기(); 대기 = p[0].수로변환(); // 다음에 기다릴 시간 상한 = p[1].수로변환(); 최대시도 = p[2].수로변환(); 예산 = p[3].수로변환(); 결과들 = p[4]; 기다린합 = 0; 시도 = 0; 상태 = ""; // 크레이콘에는 do-while이 없다: 동안 (참)으로 들어가서 끝에서 멈출지 묻는다(첫 시도는 언제나 한다) 동안 (참) { 결과 = 결과들[시도]; 시도++; 만약 (결과 == "S") { 상태 = "ok"; } 아니면 만약 (결과 == "X") { 상태 = "fatal"; } 아니면 만약 (시도 == 최대시도) { 상태 = "exhausted"; } 아니면 만약 (기다린합 + 대기 > 예산) { 상태 = "timeout"; } 아니면 { 기다린합 += 대기; 대기 = 대기 * 2 > 상한 ? 상한 : 대기 * 2; } 만약 (상태 != "") { 그만; } } 콘솔.쓰기(상태 + " " + 시도 + " " + 기다린합);}