{ }codelper
여러 갈래 조건포함 검사그리고·또는P0167

택배 요금표

택배 회사가 상자의 무게와 받는 지역으로 요금을 정한다. 첫 줄에 섬·산간처럼 먼 지역의 수 k가, 둘째 줄에 먼 지역의 번호 k개가 빈칸으로 나뉘어 주어진다. 셋째 줄에 상자 수 n이 주어지고, 다음 n줄에 상자마다 받는 지역 번호, 무게(그램), 배송 종류가 빈칸으로 나뉘어 주어진다. 배송 종류는 보통 배송 "N" 또는 빠른 배송 "X"이다. 기본 요금은 무게로 정한다. 1,000g 이하이면 3,500원, 1,000g 초과 3,000g 이하이면 4,000원, 3,000g 초과 7,000g 이하이면 5,000원이다. 7,000g 초과 15,000g 이하이면 6,500원, 15,000g 초과 25,000g 이하이면 8,500원이다. 25,000g을 넘는 상자는 받지 않는다. 받는 지역 번호가 먼 지역 번호 가운데 하나와 같으면 3,000원을 더한다. 빠른 배송은 받는 지역이 먼 지역이 아니고 무게가 15,000g 이하일 때만 할 수 있고, 그때 2,000원을 더한다. 빠른 배송을 할 수 없는 상자도 받지 않는다. 상자마다 요금을 한 줄에 하나씩 입력 차례대로 출력하고, 받지 않는 상자는 "접수불가"를 출력하라. 마지막 줄에 받은 상자의 수와 받은 상자 요금의 합을 빈칸 하나로 띄워 출력하라.

입력
1 ≤ k ≤ 100, 1 ≤ n ≤ 1,000, 지역 번호는 1 이상 999 이하의 정수(앞에 0을 붙이지 않음)이고 먼 지역 번호끼리는 서로 다르다, 1 ≤ 무게 ≤ 40,000
출력
상자마다 요금 또는 "접수불가", 마지막 줄에 받은 상자 수와 요금 합
예시 1 · stdin
3
12 305 7
7
12 1000 N
112 1001 N
305 3000 X
7 25000 N
50 15000 X
50 15001 X
9 25001 N
stdout
6500
4000
접수불가
11500
8500
접수불가
접수불가
4 30500
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이

먼 지역인지 묻는 "들어 있나" 검사가 첫째 함정이에요.
둘째 줄을 문자열 그대로 두고 Python "12" in line, JS·TS line.includes("12"), Java line.contains("12"), C# line.Contains("12"), C strstr처럼 찾으면 부분 문자열을 찾기 때문에 "112" 안의 "12"도 찾아져요.
번호를 수로 바꿔 모아 두고 Python set의 in, JS·TS Set.has, Java HashSet.contains, C# HashSet<int>.Contains, C++ unordered_set::count(C++20은 contains)로 물어야 해요.
C에는 집합이 없지만 번호가 1~999라서 is_remote[번호] 표 하나가 곧 집합이에요.
크레이콘은 콘솔.수들읽기()로 받은 수 목록에 목록.있나(r)를 써요.
목록의 수와 줄에서 자른 문자열("12")을 비교하면 같지 않으니 수로변환()으로 맞춰야 해요.
둘째 함정은 무게 칸이에요.
여러 갈래 조건은 위에서부터 처음 참인 갈래 하나만 실행하므로, 작은 칸부터 <=로 묻고 else if(Python elif, 크레이콘 아니면 만약)로 이으면 아래 끝은 묻지 않아도 돼요.
else 없이 if만 늘어놓으면 500g 상자도 다음 if들이 모두 참이라 요금이 8,500원으로 덮여요.
<로 물으면 딱 1,000g인 상자가 한 칸 비싸져요.
셋째로, 빠른 배송 조건은 두 조건이 모두 참이어야 하니 Python은 not far and w <= 15000, 나머지 일곱 언어는 !far && w <= 15000이에요.
||로 쓰면 먼 지역의 가벼운 상자도 빠른 배송을 받아요.
Java는 "X"를 ==로 비교하면 내용이 아니라 같은 객체인지를 물으니 equals를 써요(C#·Python·JS·크레이콘의 ==는 내용을 비교해요).

Pythonmain.py · 40 줄
def base_fee(w):    # 아래 칸부터 차례로 묻는다: 앞 조건이 거짓일 때만 다음 조건을 보니 칸의 아래 끝은 따로 묻지 않는다    if w <= 1000:        return 3500    elif w <= 3000:        return 4000    elif w <= 7000:        return 5000    elif w <= 15000:        return 6500    elif w <= 25000:        return 8500    else:        return None  # 25,000g을 넘으면 받지 않는다  input()  # kremote = set(map(int, input().split()))  # 수로 바꾼 집합: "12"가 "112" 안에 있다고 착각하지 않는다n = int(input())accepted = 0total = 0for _ in range(n):    r, w, s = input().split()    r, w = int(r), int(w)    fee = base_fee(w)    far = r in remote    if fee is not None and far:        fee += 3000    if fee is not None and s == "X":        if not far and w <= 15000:  # 빠른 배송은 두 조건을 모두 지켜야 한다            fee += 2000        else:            fee = None    if fee is None:        print("접수불가")    else:        print(fee)        accepted += 1        total += feeprint(accepted, total)
JavaScriptmain.js · 36 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");// 아래 칸부터 차례로 묻는다: 앞 조건이 거짓일 때만 다음 조건을 보니 칸의 아래 끝은 따로 묻지 않는다const baseFee = (w) => {  if (w <= 1000) return 3500;  else if (w <= 3000) return 4000;  else if (w <= 7000) return 5000;  else if (w <= 15000) return 6500;  else if (w <= 25000) return 8500;  else return null; // 25,000g을 넘으면 받지 않는다};// 수로 바꾼 Set: 줄 문자열에 includes를 쓰면 "12"가 "112" 안에서 찾아진다const remote = new Set(lines[1].trim().split(/\s+/).filter((x) => x !== "").map(Number));const n = Number(lines[2]);const out = [];let accepted = 0;let total = 0;for (let i = 0; i < n; i++) {  const [rText, wText, s] = lines[3 + i].trim().split(/\s+/);  const r = Number(rText);  const w = Number(wText);  let fee = baseFee(w);  const far = remote.has(r);  if (fee !== null && far) fee += 3000;  if (fee !== null && s === "X") {    if (!far && w <= 15000) fee += 2000; // 빠른 배송은 두 조건을 모두 지켜야 한다    else fee = null;  }  if (fee === null) out.push("접수불가");  else {    out.push(String(fee));    accepted++;    total += fee;  }}out.push(`${accepted} ${total}`);console.log(out.join("\n"));
TypeScriptmain.ts · 37 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");// 아래 칸부터 차례로 묻는다: 앞 조건이 거짓일 때만 다음 조건을 보니 칸의 아래 끝은 따로 묻지 않는다const baseFee = (w: number): number | null => {  if (w <= 1000) return 3500;  else if (w <= 3000) return 4000;  else if (w <= 7000) return 5000;  else if (w <= 15000) return 6500;  else if (w <= 25000) return 8500;  else return null; // 25,000g을 넘으면 받지 않는다};// 수로 바꾼 Set: 줄 문자열에 includes를 쓰면 "12"가 "112" 안에서 찾아진다const remote = new Set(lines[1].trim().split(/\s+/).filter((x) => x !== "").map(Number));const n = Number(lines[2]);const out: string[] = [];let accepted = 0;let total = 0;for (let i = 0; i < n; i++) {  const [rText, wText, s] = lines[3 + i].trim().split(/\s+/);  const r = Number(rText);  const w = Number(wText);  let fee: number | null = baseFee(w);  const far = remote.has(r);  if (fee !== null && far) fee += 3000;  if (fee !== null && s === "X") {    if (!far && w <= 15000) fee += 2000; // 빠른 배송은 두 조건을 모두 지켜야 한다    else fee = null;  }  if (fee === null) out.push("접수불가");  else {    out.push(String(fee));    accepted++;    total += fee;  }}out.push(`${accepted} ${total}`);console.log(out.join("\n"));
JavaMain.java · 51 줄
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.HashSet;import java.util.Set; public class Main {    static final int REJECT = -1;     // 아래 칸부터 차례로 묻는다: 앞 조건이 거짓일 때만 다음 조건을 보니 칸의 아래 끝은 따로 묻지 않는다    static int baseFee(int w) {        if (w <= 1000) return 3500;        else if (w <= 3000) return 4000;        else if (w <= 7000) return 5000;        else if (w <= 15000) return 6500;        else if (w <= 25000) return 8500;        else return REJECT; // 25,000g을 넘으면 받지 않는다    }     public static void main(String[] args) throws Exception {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        in.readLine(); // k        Set<Integer> remote = new HashSet<>();        for (String c : in.readLine().trim().split("\\s+")) {            if (!c.isEmpty()) remote.add(Integer.parseInt(c));        }        int n = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        int accepted = 0;        long total = 0;        for (int i = 0; i < n; i++) {            String[] p = in.readLine().trim().split("\\s+");            int r = Integer.parseInt(p[0]), w = Integer.parseInt(p[1]);            int fee = baseFee(w);            boolean far = remote.contains(r);            if (fee != REJECT && far) fee += 3000;            if (fee != REJECT && p[2].equals("X")) { // 문자열은 ==가 아니라 equals로 비교한다                if (!far && w <= 15000) fee += 2000; // 빠른 배송은 두 조건을 모두 지켜야 한다                else fee = REJECT;            }            if (fee == REJECT) {                out.append("접수불가\n");            } else {                out.append(fee).append('\n');                accepted++;                total += fee;            }        }        out.append(accepted).append(' ').append(total).append('\n');        System.out.print(out);    }}
C#Main.cs · 53 줄
using System;using System.Collections.Generic;using System.Linq;using System.Text; class Program{    // 아래 칸부터 차례로 묻는다: 앞 조건이 거짓일 때만 다음 조건을 보니 칸의 아래 끝은 따로 묻지 않는다    static int? BaseFee(int w)    {        if (w <= 1000) return 3500;        else if (w <= 3000) return 4000;        else if (w <= 7000) return 5000;        else if (w <= 15000) return 6500;        else if (w <= 25000) return 8500;        else return null; // 25,000g을 넘으면 받지 않는다    }     static void Main()    {        Console.ReadLine(); // k        var remote = new HashSet<int>(Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse));        int n = int.Parse(Console.ReadLine());        var sb = new StringBuilder();        int accepted = 0;        long total = 0;        for (int i = 0; i < n; i++)        {            string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);            int r = int.Parse(p[0]), w = int.Parse(p[1]);            int? fee = BaseFee(w);            bool far = remote.Contains(r);            if (fee != null && far) fee += 3000;            if (fee != null && p[2] == "X")            {                if (!far && w <= 15000) fee += 2000; // 빠른 배송은 두 조건을 모두 지켜야 한다                else fee = null;            }            if (fee == null)            {                sb.Append("접수불가\n");            }            else            {                sb.Append(fee.Value).Append('\n');                accepted++;                total += fee.Value;            }        }        sb.Append(accepted).Append(' ').Append(total).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 48 줄
#include <iostream>#include <optional>#include <string>#include <unordered_set> // 아래 칸부터 차례로 묻는다: 앞 조건이 거짓일 때만 다음 조건을 보니 칸의 아래 끝은 따로 묻지 않는다std::optional<int> baseFee(int w) {    if (w <= 1000) return 3500;    else if (w <= 3000) return 4000;    else if (w <= 7000) return 5000;    else if (w <= 15000) return 6500;    else if (w <= 25000) return 8500;    else return std::nullopt; // 25,000g을 넘으면 받지 않는다} int main() {    int k, n;    std::cin >> k;    std::unordered_set<int> remote;    for (int i = 0; i < k; i++) {        int code;        std::cin >> code;        remote.insert(code);    }    std::cin >> n;    int accepted = 0;    long long total = 0;    for (int i = 0; i < n; i++) {        int r, w;        std::string s;        std::cin >> r >> w >> s;        std::optional<int> fee = baseFee(w);        bool far = remote.count(r) > 0; // C++20부터는 remote.contains(r)        if (fee && far) *fee += 3000;        if (fee && s == "X") {            if (!far && w <= 15000) *fee += 2000; // 빠른 배송은 두 조건을 모두 지켜야 한다            else fee.reset();        }        if (!fee) {            std::cout << "접수불가\n";        } else {            std::cout << *fee << '\n';            accepted++;            total += *fee;        }    }    std::cout << accepted << ' ' << total << '\n';}
Cmain.c · 50 줄
#include <stdio.h>#include <string.h> #define REJECT -1 /* 아래 칸부터 차례로 묻는다: 앞 조건이 거짓일 때만 다음 조건을 보니 칸의 아래 끝은 따로 묻지 않는다 */int base_fee(int w) {    if (w <= 1000) return 3500;    else if (w <= 3000) return 4000;    else if (w <= 7000) return 5000;    else if (w <= 15000) return 6500;    else if (w <= 25000) return 8500;    else return REJECT; /* 25,000g을 넘으면 받지 않는다 */} int main(void) {    /* 지역 번호는 1~999라서 번호를 칸 번호로 쓰는 표가 곧 "들어 있나" 검사다 */    static int is_remote[1000];    int k, n;    scanf("%d", &k);    for (int i = 0; i < k; i++) {        int code;        scanf("%d", &code);        is_remote[code] = 1;    }    scanf("%d", &n);    int accepted = 0;    long total = 0;    for (int i = 0; i < n; i++) {        int r, w;        char s[4];        scanf("%d %d %3s", &r, &w, s);        int fee = base_fee(w);        int far = is_remote[r];        if (fee != REJECT && far) fee += 3000;        if (fee != REJECT && strcmp(s, "X") == 0) {            if (!far && w <= 15000) fee += 2000; /* 빠른 배송은 두 조건을 모두 지켜야 한다 */            else fee = REJECT;        }        if (fee == REJECT) {            printf("접수불가\n");        } else {            printf("%d\n", fee);            accepted++;            total += fee;        }    }    printf("%d %ld\n", accepted, total);    return 0;}
Craykonmain.cray · 65 줄
// 아래 칸부터 차례로 묻는다: 앞 조건이 거짓일 때만 다음 조건을 보니 칸의 아래 끝은 따로 묻지 않는다기본요금(w){    만약 (w <= 1000)    {        돌려주기 3500;    }    아니면 만약 (w <= 3000)    {        돌려주기 4000;    }    아니면 만약 (w <= 7000)    {        돌려주기 5000;    }    아니면 만약 (w <= 15000)    {        돌려주기 6500;    }    아니면 만약 (w <= 25000)    {        돌려주기 8500;    }    돌려주기 -1; // 25,000g을 넘으면 받지 않는다} 콘솔.줄읽기(); // kremote = 콘솔.수들읽기(); // 수 목록: 문자열 "12 305"에서 찾으면 "12"가 "112" 안에서도 찾아진다n = 콘솔.줄읽기().수로변환();accepted = 0;total = 0;반복 (i = 0; i < n; i++){    칸 = 콘솔.줄읽기().나누기();    r = 칸[0].수로변환();    w = 칸[1].수로변환();    fee = 기본요금(w);    far = remote.있나(r);    만약 (fee != -1 && far)    {        fee += 3000;    }    만약 (fee != -1 && 칸[2] == "X")    {        만약 (!far && w <= 15000)        {            fee += 2000;        }        아니면        {            fee = -1;        }    }    만약 (fee == -1)    {        콘솔.쓰기("접수불가");    }    아니면    {        콘솔.쓰기(fee);        accepted += 1;        total += fee;    }}콘솔.쓰기(accepted + " " + total);