{ }codelper
数の読み込み64ビット整数P0231

どこででも改行される秤の記録

倉庫の秤が、箱に入った品物の重さを紙テープに印字しておいた。
紙テープの幅が狭いので、数が終わるたびにどこででも次の行に移ることがある。
数と数の間には空白が一つ以上あることがあり、行の前後に空白があったり、空行がはさまっていたりすることもある。
一つの数が二行に分かれて切れることはない。
入力全体を最初から順に読んだ整数は、次の意味を持つ。
いちばん最初の数は箱の数 k である。
その後、1 番の箱から順に、箱ごとに品物の数 m が来て、続いてその箱の品物の重さ m 個が来る。
m が 0 なら空の箱で、その箱の重さは一つも来ない。
箱ごとに一行に重さの合計を出力せよ(空の箱は 0)。
最後の行には、重さの合計がいちばん大きい箱の番号を出力せよ。
合計がいちばん大きい箱が複数あれば、その中でいちばん小さい番号を出力する。

入力
1 ≤ k ≤ 1,000、0 ≤ m ≤ 10,000、すべての箱の m の和は 20,000 以下、1 ≤ 重さ ≤ 1,000,000,000(すべて整数)、一行の数は 100 個以下
出力
k 行:箱ごとの重さの合計 / 最後の行:合計がいちばん大きい箱の番号
例 1 · stdin
3 2 500
 700
0

4 100 200
   300 400
stdout
1200
0
1000
1
例 2 · stdin
2
1
800
2 300
500
stdout
800
800
1
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

この問題の要は、入力を行ではなく数の流れとして読むことです。
C scanf("%d")、C++ std::cin >>、Java Scanner.nextInt() は数の前の空白・改行をすべて読み飛ばして次の数を一つ読むので、どこで改行されていても関係ありません。
逆に Python input()、C# Console.ReadLine()、Java BufferedReader.readLine()、Craykon コンソール.行読み()・コンソール.数読み() は一行ずつ読みます。
一つの箱が一行に全部あると思って一行ごとに箱を一つ処理すると間違えます。
そこで Python は sys.stdin.read().split()、JS・TS は readFileSync(0, "utf8").trim().split(/\s+/)、C# は Console.In.ReadToEnd().Split(..., StringSplitOptions.RemoveEmptyEntries) で入力全体を一度に分けます。
Java で速く読むには、StringTokenizer が空になったら次の行を読む小さな関数を用意します。
Craykon は行ごとに 行.分ける() で断片を取り出しながら、いま待っているのが箱の数か品物の数か重さかを変数で覚えておきます。
区切りも罠です。
JS split(" ") は空白一つだけを区切りと見るので "3\n2" や "" のような断片ができ、Number がそれを NaN や 0 に変えます。
C# で RemoveEmptyEntries を抜くと、空白が重なったところと空行で "" ができて int.Parse が FormatException を出します。
Python split() と Craykon 分ける() は区切りを渡さなければ空白がいくつあっても一つと見て、空の断片を捨てます(Python で split(" ") と書くと空の断片ができます)。
重さの合計は 10^13 まで大きくなり 32 ビットの int を超えるので、Java・C# は long、C・C++ は long long を使います。
JS・TS・Craykon の数は 2^53 まで整数が正確で、Python の整数には大きさの制限がありません。
いちばん重い箱は >= ではなく > で更新すると、同じ合計のとき前の番号が残ります。

Pythonmain.py · 13 行
import sys # 줄과 상관없이 입력 전체를 빈칸·줄바꿈으로 나눈 수의 흐름으로 읽는다nums = iter(map(int, sys.stdin.read().split()))k = next(nums)best, best_total = 1, -1for box in range(1, k + 1):    m = next(nums)    total = sum(next(nums) for _ in range(m))    print(total)    if total > best_total:  # 같으면 앞의 상자를 그대로 둔다        best, best_total = box, totalprint(best)
JavaScriptmain.js · 19 行
// 앞뒤 빈칸을 없앤 뒤 /\s+/로 나누면 여러 빈칸·줄바꿈·빈 줄이 모두 하나의 구분이 된다const nums = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);let at = 0;const k = nums[at++];const out = [];let best = 1;let bestTotal = -1;for (let box = 1; box <= k; box++) {  const m = nums[at++];  let total = 0; // 최대 10^13: 2^53 안이라 정확하다  for (let i = 0; i < m; i++) total += nums[at++];  out.push(total);  if (total > bestTotal) {    best = box;    bestTotal = total;  }}out.push(best);console.log(out.join("\n"));
TypeScriptmain.ts · 21 行
import { readFileSync } from "node:fs";// 앞뒤 빈칸을 없앤 뒤 /\s+/로 나누면 여러 빈칸·줄바꿈·빈 줄이 모두 하나의 구분이 된다const nums: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);let at = 0;const next = (): number => nums[at++];const k = next();const out: number[] = [];let best = 1;let bestTotal = -1;for (let box = 1; box <= k; box++) {  const m = next();  let total = 0; // 최대 10^13: 2^53 안이라 정확하다  for (let i = 0; i < m; i++) total += next();  out.push(total);  if (total > bestTotal) {    best = box;    bestTotal = total;  }}out.push(best);console.log(out.join("\n"));
JavaMain.java · 34 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer; public class Main {    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));    static StringTokenizer tok = new StringTokenizer("");     // 지금 줄의 수를 다 쓰면 다음 줄을 읽는다: 줄이 어디서 바뀌든 수만 차례로 나온다    static long next() throws IOException {        while (!tok.hasMoreTokens()) tok = new StringTokenizer(in.readLine());        return Long.parseLong(tok.nextToken());    }     public static void main(String[] args) throws IOException {        int k = (int) next();        StringBuilder out = new StringBuilder();        int best = 1;        long bestTotal = -1;        for (int box = 1; box <= k; box++) {            long m = next();            long total = 0; // 최대 10^13: int로는 넘친다            for (long i = 0; i < m; i++) total += next();            out.append(total).append('\n');            if (total > bestTotal) {                best = box;                bestTotal = total;            }        }        out.append(best).append('\n');        System.out.print(out);    }}
C#Main.cs · 30 行
using System;using System.Text; class Program{    static void Main()    {        // 입력 전체를 읽고 빈칸·줄바꿈으로 나눈다. 빈 조각(빈칸이 겹친 곳, 빈 줄)은 버린다        string[] nums = Console.In.ReadToEnd().Split(new[] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);        int at = 0;        int k = int.Parse(nums[at++]);        var out_ = new StringBuilder();        int best = 1;        long bestTotal = -1;        for (int box = 1; box <= k; box++)        {            int m = int.Parse(nums[at++]);            long total = 0; // 최대 10^13: int로는 넘친다            for (int i = 0; i < m; i++) total += long.Parse(nums[at++]);            out_.Append(total).Append('\n');            if (total > bestTotal)            {                best = box;                bestTotal = total;            }        }        out_.Append(best).Append('\n');        Console.Write(out_);    }}
C++main.cpp · 27 行
#include <iostream> int main() {    std::ios::sync_with_stdio(false);    std::cin.tie(nullptr);    // >>는 빈칸·줄바꿈을 모두 건너뛰고 다음 수를 읽는다    int k;    std::cin >> k;    int best = 1;    long long bestTotal = -1;    for (int box = 1; box <= k; box++) {        int m;        std::cin >> m;        long long total = 0; // 최대 10^13: int로는 넘친다        for (int i = 0; i < m; i++) {            long long w;            std::cin >> w;            total += w;        }        std::cout << total << '\n';        if (total > bestTotal) {            best = box;            bestTotal = total;        }    }    std::cout << best << '\n';}
Cmain.c · 26 行
#include <stdio.h> int main(void) {    /* scanf("%d")는 수 앞의 빈칸·줄바꿈을 모두 건너뛴다: 줄이 어디서 바뀌든 상관없다 */    int k;    scanf("%d", &k);    int best = 1;    long long best_total = -1;    for (int box = 1; box <= k; box++) {        int m;        scanf("%d", &m);        long long total = 0; /* 최대 10^13: int로는 넘친다 */        for (int i = 0; i < m; i++) {            long long w;            scanf("%lld", &w);            total += w;        }        printf("%lld\n", total);        if (total > best_total) {            best = box;            best_total = total;        }    }    printf("%d\n", best);    return 0;}
Craykonmain.cray · 44 行
// 줄마다 수의 개수가 제각각이다. 줄을 읽어 수를 하나씩 꺼내며// "지금 무엇을 기다리는지"(상자 수 → 물건 수 → 무게)를 따라간다k = -1; // 아직 상자 수를 읽지 않았다box = 0; // 지금 상자 번호left = -1; // 이 상자에 남은 무게 수(-1이면 물건 수를 기다린다)total = 0;best = 1;bestTotal = -1;줄 = コンソール.行読み();間 (줄 != なし){    それぞれ (조각 の中 줄.分ける())    {        x = 조각.数に();        もし (k == -1)        {            k = x;        }        でなければ もし (left == -1)        {            box++;            left = x;            total = 0;        }        でなければ        {            total += x;            left--;        }        // 무게를 다 읽었으면(빈 상자는 바로) 상자 하나가 끝난다        もし (left == 0)        {            コンソール.書く(total);            もし (total > bestTotal)            {                best = box;                bestTotal = total;            }            left = -1;        }    }    줄 = コンソール.行読み();}コンソール.書く(best);