一块拼布有 R 行、C 列,每个格子里写着一个英文小写字母。 行从上往下从 1 开始编号,列从左往右从 1 开始编号。 (行号 + 列号 − 1)等于 d 的格子组成 d 号斜线。 斜线从 1 号到 R + C − 1 号。 读一条斜线时,从这条斜线最下面一行的格子开始往上一行一行走(从左下到右上),把字符连起来。 从 a 号斜线开始每次跳 s 条,按顺序读 a, a + s, a + 2 × s, … 中编号不超过 b 的斜线。 第一行给出 R 和 C,用一个空格隔开。 接下来 R 行,每行给出一个长度为 C 的字符串。 最后一行给出 a、b、s,用一个空格隔开。 对读到的每条斜线,把连起来的字符串输出在一行,从编号小的斜线开始。 不要去看不在斜线上的格子,请算出循环的起点和终点,只走这条斜线上的格子。
输入
1 ≤ R ≤ 100。 1 ≤ C ≤ 100。 1 ≤ a ≤ b ≤ R + C − 1。 1 ≤ s ≤ R + C − 1。 字符都是英文小写字母
输出
读到的每条斜线一行
样例 1 · stdin
3 4
abcd
efgh
ijkl
2 6 2
stdout
eb
jgd
l
样例 2 · stdin
4 2
ab
cd
ef
gh
1 5 1
stdout
a
cb
ed
gf
h
main.py
错误列表00F8 ↓ · ⇧F8 ↑
输入(stdin)
运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。
$ 就绪
请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。
其他语言怎么写?查看各语言题解 · 8 种语言题解
跳着数的循环,Python 写 for d in range(a, b + 1, s),其他语言写 for (d = a; d <= b; d += s)(Craykon 是 循环 (d = a; d <= b; d += s))。 在一条斜线里,从 0 数起的行 r 和列 c 满足 r + c = d − 1,所以行从 min(d - 1, R - 1) 倒着数到 max(0, d - C),列用 d - 1 - r 求出。 倒着数在 Python 中是 range(low, high - 1, -1),其他语言是 for (r = low; r >= high; r--)。 较小值和较大值,Python 用 min/max,JS・TS・Java 用 Math.min/Math.max,C# 用 Math.Min/Math.Max,C++ 用 std::min/std::max,Craykon 用 数学.较小值/数学.较大值,C 写成 a < b ? a : b。 陷阱 ① Python 的 range 不包含终点。 写成 range(a, b, s),当 (b − a) 是 s 的倍数时会漏掉 b 号斜线(第一个样例的最后一行 l 不会输出)。 倒着数时也一样,range(low, high, -1) 会漏掉最上面的格子(第一个样例变成 e、jg 和什么都没有的一行)。 ② 最上面的行由列数 C 决定。 像 max(0, d - R) 这样用 R,只有正方形时才对;横长的拼布会漏字符,竖长的拼布会读到不存在的格子。 ③ 不计算范围而是走遍所有行、只检查 c < C 的话,c 为负数的格子会留下来。 Python 会把 grid[r][-1] 不报错地读成该行最后一个字符,所以第一个样例的第一行变成 leb。 JS・TS 返回 undefined,于是接上 "undefined";Java・C# 以异常停止;Craykon 也会停止,提示字符串只有 0~3 号;C・C++ 会读到数组外面。 ④ 方向反过来(从上面的行到下面的行)走,字符串就反了。 ⑤ 把 d += s 写成 d++ 就不会跳,所有斜线都会输出。
Pythonmain.py · 20 行
import sysdef main(): lines = sys.stdin.read().split() R, C = int(lines[0]), int(lines[1]) grid = lines[2:2 + R] a, b, s = (int(x) for x in lines[2 + R:5 + R]) out = [] for d in range(a, b + 1, s): # range는 끝을 넣지 않으므로 b + 1까지 # d번 사선의 칸은 (0부터 센) 줄 r + 칸 c = d - 1을 만족한다 low = min(d - 1, R - 1) # 가장 아래 줄 high = max(0, d - C) # 가장 위 줄 # 거꾸로 셀 때도 끝은 들어가지 않는다: high - 1까지 out.append("".join(grid[r][d - 1 - r] for r in range(low, high - 1, -1))) print("\n".join(out))main()
JavaScriptmain.js · 18 行
const lines = require("fs").readFileSync(0, "utf8").split(/\s+/).filter((s) => s !== "");const R = Number(lines[0]);const C = Number(lines[1]);const grid = lines.slice(2, 2 + R);const [a, b, s] = lines.slice(2 + R, 5 + R).map(Number);const out = [];for (let d = a; d <= b; d += s) { // d번 사선의 칸은 (0부터 센) 줄 r + 칸 c = d - 1을 만족한다 const low = Math.min(d - 1, R - 1); // 가장 아래 줄 const high = Math.max(0, d - C); // 가장 위 줄 let line = ""; for (let r = low; r >= high; r--) { line += grid[r][d - 1 - r]; } out.push(line);}console.log(out.join("\n"));
TypeScriptmain.ts · 22 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split(/\s+/).filter((s) => s !== "");const R: number = Number(lines[0]);const C: number = Number(lines[1]);const grid: string[] = lines.slice(2, 2 + R);const a: number = Number(lines[2 + R]);const b: number = Number(lines[3 + R]);const s: number = Number(lines[4 + R]);const out: string[] = [];for (let d = a; d <= b; d += s) { // d번 사선의 칸은 (0부터 센) 줄 r + 칸 c = d - 1을 만족한다 const low: number = Math.min(d - 1, R - 1); // 가장 아래 줄 const high: number = Math.max(0, d - C); // 가장 위 줄 let line = ""; for (let r = low; r >= high; r--) { line += grid[r][d - 1 - r]; } out.push(line);}console.log(out.join("\n"));
JavaMain.java · 30 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer;public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(in.readLine()); int R = Integer.parseInt(st.nextToken()), C = Integer.parseInt(st.nextToken()); String[] grid = new String[R]; for (int r = 0; r < R; r++) { grid[r] = in.readLine().trim(); } st = new StringTokenizer(in.readLine()); int a = Integer.parseInt(st.nextToken()), b = Integer.parseInt(st.nextToken()), s = Integer.parseInt(st.nextToken()); StringBuilder out = new StringBuilder(); for (int d = a; d <= b; d += s) { // d번 사선의 칸은 (0부터 센) 줄 r + 칸 c = d - 1을 만족한다 int low = Math.min(d - 1, R - 1); // 가장 아래 줄 int high = Math.max(0, d - C); // 가장 위 줄 for (int r = low; r >= high; r--) { out.append(grid[r].charAt(d - 1 - r)); } out.append('\n'); } System.out.print(out); }}
C#Main.cs · 32 行
using System;using System.Text;class Program{ static void Main() { string[] head = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int R = int.Parse(head[0]), C = int.Parse(head[1]); string[] grid = new string[R]; for (int r = 0; r < R; r++) { grid[r] = Console.ReadLine().Trim(); } string[] tail = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int a = int.Parse(tail[0]), b = int.Parse(tail[1]), s = int.Parse(tail[2]); var sb = new StringBuilder(); for (int d = a; d <= b; d += s) { // d번 사선의 칸은 (0부터 센) 줄 r + 칸 c = d - 1을 만족한다 int low = Math.Min(d - 1, R - 1); // 가장 아래 줄 int high = Math.Max(0, d - C); // 가장 위 줄 for (int r = low; r >= high; r--) { sb.Append(grid[r][d - 1 - r]); } sb.Append('\n'); } Console.Write(sb); }}
C++main.cpp · 26 行
#include <algorithm>#include <iostream>#include <string>#include <vector>int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int R, C; std::cin >> R >> C; std::vector<std::string> grid(R); for (auto& row : grid) std::cin >> row; int a, b, s; std::cin >> a >> b >> s; for (int d = a; d <= b; d += s) { // d번 사선의 칸은 (0부터 센) 줄 r + 칸 c = d - 1을 만족한다 int low = std::min(d - 1, R - 1); // 가장 아래 줄 int high = std::max(0, d - C); // 가장 위 줄 std::string line; for (int r = low; r >= high; r--) { line += grid[r][d - 1 - r]; } std::cout << line << '\n'; }}
Cmain.c · 23 行
#include <stdio.h>static char grid[100][101];int main(void) { int R, C, a, b, s; scanf("%d %d", &R, &C); for (int r = 0; r < R; r++) { scanf("%100s", grid[r]); } scanf("%d %d %d", &a, &b, &s); for (int d = a; d <= b; d += s) { /* d번 사선의 칸은 (0부터 센) 줄 r + 칸 c = d - 1을 만족한다 */ int low = d - 1 < R - 1 ? d - 1 : R - 1; /* 가장 아래 줄 */ int high = d - C > 0 ? d - C : 0; /* 가장 위 줄 */ for (int r = low; r >= high; r--) { putchar(grid[r][d - 1 - r]); } putchar('\n'); } return 0;}
Craykonmain.cray · 25 行
head = 控制台.读数字();R = head[0];C = head[1];grid = [];循环 (r = 0; r < R; r++){ grid.添加(控制台.读行().去空白());}tail = 控制台.读数字();a = tail[0];b = tail[1];s = tail[2];循环 (d = a; d <= b; d += s){ // d번 사선의 칸은 (0부터 센) 줄 r + 칸 c = d - 1을 만족한다 low = 数学.较小值(d - 1, R - 1); high = 数学.较大值(0, d - C); line = ""; 循环 (r = low; r >= high; r--) { line += grid[r][d - 1 - r]; } 控制台.输出(line);}