教室に席が一列に n 個あり、席番号は左から 1, 2, …, n である。 一行目に n が、二行目に最初の席に座った生徒の名前 n 個が席の順に空白一つずつ区切って与えられる。 三行目に入れ替えの数 m が、続く m 行に入れ替え「i j」が一行に一つずつ与えられる。 担任の先生はこの入れ替えを与えられた順に行う。 入れ替え「i j」は、i 番の席の生徒と j 番の席の生徒が席を交換することである。 i と j が同じなら何も起こらない。 すべての入れ替えのあと、一行目に席の順に生徒の名前を空白一つずつ区切って出力せよ。 二行目には、最初の席と最後の席が違う生徒の数 k を出力せよ。 続く k 行に、そのような生徒ごとに「名前 最初の席 最後の席」を空白一つずつ区切って出力せよ。 この k 行は、最初の席番号が小さい生徒から出力する。 何度か動いても最後に最初の席に戻った生徒は数えない。 k が 0 なら二行目の 0 までだけを出力する。
入力
1 ≤ n ≤ 1000、0 ≤ m ≤ 2000、1 ≤ i, j ≤ n。 名前は英小文字 1 ~ 10 文字ですべて異なる
import sysdata = sys.stdin.read().split()n = int(data[0])seats = data[1:1 + n]start = seats[:] # 처음 자리를 따로 복사해 둔다(start = seats 는 같은 목록에 이름만 둘)m = int(data[1 + n])pos = 2 + nfor _ in range(m): i, j = int(data[pos]) - 1, int(data[pos + 1]) - 1 pos += 2 seats[i], seats[j] = seats[j], seats[i]now = {name: k for k, name in enumerate(seats)}moved = [(name, k + 1, now[name] + 1) for k, name in enumerate(start) if now[name] != k]print(" ".join(seats))print(len(moved))for name, a, b in moved: print(name, a, b)
JavaScriptmain.js · 20 行
const data = require("fs").readFileSync(0, "utf8").trim().split(/\s+/);const n = Number(data[0]);const seats = data.slice(1, 1 + n);const start = [...seats]; // 복사본. const start = seats 는 같은 배열을 가리킨다const m = Number(data[1 + n]);let pos = 2 + n;for (let k = 0; k < m; k++, pos += 2) { const i = Number(data[pos]) - 1; const j = Number(data[pos + 1]) - 1; [seats[i], seats[j]] = [seats[j], seats[i]];}const now = new Map(seats.map((name, k) => [name, k]));const out = [seats.join(" ")];const moved = [];start.forEach((name, k) => { if (now.get(name) !== k) moved.push(`${name} ${k + 1} ${now.get(name) + 1}`);});out.push(String(moved.length), ...moved);console.log(out.join("\n"));
TypeScriptmain.ts · 22 行
import { readFileSync } from "node:fs";const data: string[] = readFileSync(0, "utf8").trim().split(/\s+/);const n = Number(data[0]);const seats: string[] = data.slice(1, 1 + n);const start: string[] = [...seats]; // 복사본. const start = seats 는 같은 배열을 가리킨다const m = Number(data[1 + n]);let pos = 2 + n;for (let k = 0; k < m; k++, pos += 2) { const i = Number(data[pos]) - 1; const j = Number(data[pos + 1]) - 1; [seats[i], seats[j]] = [seats[j], seats[i]];}const now = new Map<string, number>(seats.map((name, k): [string, number] => [name, k]));const out: string[] = [seats.join(" ")];const moved: string[] = [];start.forEach((name, k) => { const at = now.get(name)!; if (at !== k) moved.push(`${name} ${k + 1} ${at + 1}`);});out.push(String(moved.length), ...moved);console.log(out.join("\n"));
JavaMain.java · 33 行
import java.io.*;import java.util.*;public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine().trim()); String[] seats = br.readLine().trim().split(" "); String[] start = seats.clone(); // String[] start = seats; 는 같은 배열을 가리킨다 int m = Integer.parseInt(br.readLine().trim()); for (int k = 0; k < m; k++) { StringTokenizer st = new StringTokenizer(br.readLine()); int i = Integer.parseInt(st.nextToken()) - 1; int j = Integer.parseInt(st.nextToken()) - 1; String tmp = seats[i]; seats[i] = seats[j]; seats[j] = tmp; } Map<String, Integer> now = new HashMap<>(); for (int k = 0; k < n; k++) now.put(seats[k], k); StringBuilder moved = new StringBuilder(); int count = 0; for (int k = 0; k < n; k++) { int at = now.get(start[k]); if (at != k) { count++; moved.append(start[k]).append(' ').append(k + 1).append(' ').append(at + 1).append('\n'); } } System.out.print(String.join(" ", seats) + "\n" + count + "\n" + moved); }}
C#Main.cs · 33 行
using System;using System.Collections.Generic;using System.Text;class Program{ static void Main() { int n = int.Parse(Console.ReadLine().Trim()); string[] seats = Console.ReadLine().Trim().Split(' '); string[] start = (string[])seats.Clone(); // string[] start = seats; 는 같은 배열을 가리킨다 int m = int.Parse(Console.ReadLine().Trim()); for (int k = 0; k < m; k++) { string[] p = Console.ReadLine().Trim().Split(' '); int i = int.Parse(p[0]) - 1, j = int.Parse(p[1]) - 1; (seats[i], seats[j]) = (seats[j], seats[i]); } var now = new Dictionary<string, int>(); for (int k = 0; k < n; k++) now[seats[k]] = k; var moved = new List<string>(); for (int k = 0; k < n; k++) { int at = now[start[k]]; if (at != k) moved.Add($"{start[k]} {k + 1} {at + 1}"); } var sb = new StringBuilder(); sb.Append(string.Join(" ", seats)).Append('\n').Append(moved.Count).Append('\n'); foreach (string line in moved) sb.Append(line).Append('\n'); Console.Write(sb); }}
C++main.cpp · 33 行
#include <iostream>#include <string>#include <unordered_map>#include <utility>#include <vector>int main() { int n, m; std::cin >> n; std::vector<std::string> seats(n); for (auto& s : seats) std::cin >> s; std::vector<std::string> start = seats; // vector는 = 가 통째로 복사한다(참조가 아니다) std::cin >> m; for (int k = 0; k < m; k++) { int i, j; std::cin >> i >> j; std::swap(seats[i - 1], seats[j - 1]); } std::unordered_map<std::string, int> now; for (int k = 0; k < n; k++) now[seats[k]] = k; std::string out, moved; int count = 0; for (int k = 0; k < n; k++) out += (k ? " " : "") + seats[k]; for (int k = 0; k < n; k++) { int at = now[start[k]]; if (at != k) { count++; moved += start[k] + " " + std::to_string(k + 1) + " " + std::to_string(at + 1) + "\n"; } } std::cout << out << "\n" << count << "\n" << moved;}
Cmain.c · 37 行
#include <stdio.h>#include <string.h>static char seats[1000][11];static char start[1000][11];int main(void) { int n, m; scanf("%d", &n); for (int k = 0; k < n; k++) scanf("%10s", seats[k]); memcpy(start, seats, sizeof seats); /* 배열은 = 로 복사할 수 없다: 칸을 통째로 복사 */ scanf("%d", &m); for (int k = 0; k < m; k++) { int i, j; char tmp[11]; scanf("%d %d", &i, &j); i--, j--; if (i == j) continue; /* 같은 칸끼리 strcpy 하면 겹친 복사라 안 된다 */ strcpy(tmp, seats[i]); strcpy(seats[i], seats[j]); strcpy(seats[j], tmp); } /* 처음 자리마다 지금 자리를 찾는다(n이 1000 이하라 차례로 찾아도 된다) */ static int at[1000]; int count = 0; for (int k = 0; k < n; k++) { for (int t = 0; t < n; t++) if (strcmp(seats[t], start[k]) == 0) { at[k] = t; break; } if (at[k] != k) count++; } for (int k = 0; k < n; k++) printf(k ? " %s" : "%s", seats[k]); printf("\n%d\n", count); for (int k = 0; k < n; k++) if (at[k] != k) printf("%s %d %d\n", start[k], k + 1, at[k] + 1); return 0;}
Craykonmain.cray · 35 行
n = コンソール.行読み().数に();seats = コンソール.行読み().空白除去().分ける();// start = seats; 라면 같은 목록에 이름만 둘이다. 부분목록은 새 목록을 만든다start = seats.部分リスト(0, seats.個数);m = コンソール.行読み().数に();繰り返す (k = 0; k < m; k++){ p = コンソール.数読み(); i = p[0] - 1; j = p[1] - 1; tmp = seats[i]; seats[i] = seats[j]; seats[j] = tmp;}now = 辞書();繰り返す (k = 0; k < n; k++){ now[seats[k]] = k;}moved = [];繰り返す (k = 0; k < n; k++){ at = now[start[k]]; もし (at != k) { moved.追加(start[k] + " " + (k + 1) + " " + (at + 1)); }}コンソール.書く(seats.つなぐ(" "));コンソール.書く(moved.個数);それぞれ (line の中 moved){ コンソール.書く(line);}