n 位客人围着圆桌坐下。 座位按顺时针编号为 0 到 n − 1,n − 1 号座位和 0 号座位也相邻。 第一个列出的客人总是坐 0 号座位,其余客人各坐 1 号到 n − 1 号中的一个座位。 两个座位的距离是沿桌子走较短一边所隔的座位数(座位 p 和 q 时为 |p − q| 与 n − |p − q| 中较小者)。 规则有四种。 next A B:A 与 B 的距离为 1。 apart A B:A 与 B 的距离不为 1。 cw A B:B 坐在 A 顺时针方向的下一个座位,即 B 的座位 = (A 的座位 + 1) 除以 n 的余数。 far A B k:A 与 B 的距离至少为 k。 输出满足全部 m 条规则的坐法数。 若至少有一种,再输出一行:从 0 号座位起依次写出名字时字典序最靠前的安排,名字之间用一个空格分开。 字典序按座位顺序逐个比较名字,名字之间按字符串比较(按字母顺序,前缀相同时较短的在前)。
输入
第一行为 n 和 m,第二行为 n 个互不相同的名字,接下来 m 行每行一条规则。 1 ≤ n ≤ 9,0 ≤ m ≤ 20,名字是 1~10 个小写英文字母,规则中的 A 和 B 是不同的客人,1 ≤ k ≤ 9
输出
坐法数。 若至少为 1,下一行输出字典序最靠前的安排
样例 1 · stdin
5 3
mina dan eve bo cal
next mina bo
cw dan eve
far mina cal 2
stdout
2
mina bo cal dan eve
样例 2 · stdin
2 1
bo al
apart al bo
stdout
0
main.py
错误列表00F8 ↓ · ⇧F8 ↑
输入(stdin)
运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。
$ 就绪
请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。
其他语言怎么写?查看各语言题解 · 8 种语言题解
即使有 9 位客人,其余 8 人的坐法也只有 8! = 40,320 种,所以可以全部试一遍。 从 1 号座位起依次填座,只立即检查涉及刚坐下的客人且两人都已入座的规则,一旦违反就不再往下看(剪枝)。 按名字顺序尝试,第一个找到的安排就是字典序最靠前的。 读入规则时把它变成检查函数放进列表,入座时就不必再判断种类,直接调用即可:Python lambda,JavaScript/TypeScript 箭头函数 (sa, sb) => …(TypeScript 写 type Check = (sa: number, sb: number) => boolean),Java BiPredicate<Integer, Integer> 和 check.test(…),C# Func<int, int, bool>,C++ std::function<bool(int, int)> 和 lambda [k](int sa, int sb) {…},C 用函数指针 int (*check)(int, int, int) 和 k 一起放进结构体。 Craykon 没有 lambda,所以写四个形状同为 (sa, sb, k) 的函数,用字典 checks["far"] = 멀리; 按名字找到函数,放进 [函数, a, b, k] 列表,再用 r[0](sa, sb, r[3]) 调用。 陷阱 ① 延迟绑定的 k:Python 循环里的 lambda sa, sb: dist(sa, sb) >= k 记住的是变量 k 而不是它的值,之后调用时看到的是最后一条规则的 k — 像 def at_least(k): return lambda … 这样用函数包一层。 JavaScript 的 var k 不会每轮新建,同样会出错,而 let/const 每轮新建,没问题。 Java 的 lambda 只能捕获 effectively final 的变量,所以这个错误根本编译不过;C# 在循环体内声明的变量每轮各自独立。 C++ 用 [k] 按值复制捕获。 ② 忘了 n − 1 号和 0 号相邻,只用 |p − q| 量距离。 ③ 把 cw 的方向弄反。 ④ 不固定 0 号座位,把旋转后的安排另算。
Pythonmain.py · 63 行
import sysdef main(): lines = sys.stdin.read().split("\n") n, m = map(int, lines[0].split()) names = lines[1].split() index = {name: i for i, name in enumerate(names)} def dist(sa, sb): """둥근 탁자에서 두 자리 사이의 짧은 쪽 거리""" d = abs(sa - sb) return min(d, n - d) def at_least(k): # k를 매개변수로 받아 가둔다. 반복문 안에서 lambda가 k를 바로 쓰면 마지막 k만 보게 된다 return lambda sa, sb: dist(sa, sb) >= k makers = { "next": lambda k: (lambda sa, sb: dist(sa, sb) == 1), "apart": lambda k: (lambda sa, sb: dist(sa, sb) != 1), "cw": lambda k: (lambda sa, sb: (sa + 1) % n == sb), "far": at_least, } rules_of = [[] for _ in range(n)] # 손님마다 그 손님이 나오는 규칙: (검사 함수, a, b) for line in lines[2:2 + m]: kind, x, y, *rest = line.split() a, b = index[x], index[y] check = makers[kind](int(rest[0]) if rest else 0) rules_of[a].append((check, a, b)) rules_of[b].append((check, a, b)) order = sorted(range(1, n), key=lambda g: names[g]) # 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 seat_of = [-1] * n seat_of[0] = 0 # 처음 적힌 손님은 늘 0번 자리 at_seat = [0] * n count = 0 first = None def place(seat): nonlocal count, first if seat == n: count += 1 if first is None: first = " ".join(names[g] for g in at_seat) return for g in order: if seat_of[g] != -1: continue seat_of[g] = seat at_seat[seat] = g # 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) if all(seat_of[a] < 0 or seat_of[b] < 0 or check(seat_of[a], seat_of[b]) for check, a, b in rules_of[g]): place(seat + 1) seat_of[g] = -1 place(1) print(count) if count > 0: print(first)main()
JavaScriptmain.js · 50 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, m] = lines[0].trim().split(/\s+/).map(Number);const names = lines[1].trim().split(/\s+/);const index = new Map(names.map((name, i) => [name, i]));// 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리const dist = (sa, sb) => Math.min(Math.abs(sa - sb), n - Math.abs(sa - sb));// 규칙 종류마다 "검사 함수를 만드는 함수". far는 k를 가둔 화살표 함수를 돌려준다const makers = { next: () => (sa, sb) => dist(sa, sb) === 1, apart: () => (sa, sb) => dist(sa, sb) !== 1, cw: () => (sa, sb) => (sa + 1) % n === sb, far: (k) => (sa, sb) => dist(sa, sb) >= k,};const rulesOf = Array.from({ length: n }, () => []); // 손님마다 그 손님이 나오는 규칙: { check, a, b }for (let i = 0; i < m; i++) { const [kind, x, y, k] = lines[2 + i].trim().split(/\s+/); const rule = { check: makers[kind](Number(k)), a: index.get(x), b: index.get(y) }; rulesOf[rule.a].push(rule); rulesOf[rule.b].push(rule);}// 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다const order = [...Array(n).keys()].slice(1).sort((g, h) => (names[g] < names[h] ? -1 : 1));const seatOf = new Array(n).fill(-1);seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리const atSeat = new Array(n).fill(0);let count = 0;let first = null;function place(seat) { if (seat === n) { count++; if (first === null) first = atSeat.map((g) => names[g]).join(" "); return; } for (const g of order) { if (seatOf[g] !== -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) const ok = rulesOf[g].every(({ check, a, b }) => seatOf[a] < 0 || seatOf[b] < 0 || check(seatOf[a], seatOf[b])); if (ok) place(seat + 1); seatOf[g] = -1; }}place(1);console.log(count > 0 ? `${count}\n${first}` : "0");
TypeScriptmain.ts · 58 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const [n, m] = lines[0].trim().split(/\s+/).map(Number);const names: string[] = lines[1].trim().split(/\s+/);const index = new Map<string, number>(names.map((name, i) => [name, i]));type Check = (sa: number, sb: number) => boolean;interface Rule { check: Check; a: number; b: number;}// 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리const dist = (sa: number, sb: number): number => Math.min(Math.abs(sa - sb), n - Math.abs(sa - sb));// 규칙 종류마다 "검사 함수를 만드는 함수". far는 k를 가둔 화살표 함수를 돌려준다const makers: Record<string, (k: number) => Check> = { next: () => (sa, sb) => dist(sa, sb) === 1, apart: () => (sa, sb) => dist(sa, sb) !== 1, cw: () => (sa, sb) => (sa + 1) % n === sb, far: (k) => (sa, sb) => dist(sa, sb) >= k,};const rulesOf: Rule[][] = Array.from({ length: n }, () => []); // 손님마다 그 손님이 나오는 규칙for (let i = 0; i < m; i++) { const [kind, x, y, k] = lines[2 + i].trim().split(/\s+/); const rule: Rule = { check: makers[kind](Number(k)), a: index.get(x)!, b: index.get(y)! }; rulesOf[rule.a].push(rule); rulesOf[rule.b].push(rule);}// 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다const order: number[] = [...Array(n).keys()].slice(1).sort((g, h) => (names[g] < names[h] ? -1 : 1));const seatOf: number[] = new Array<number>(n).fill(-1);seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리const atSeat: number[] = new Array<number>(n).fill(0);let count = 0;let first: string | null = null;function place(seat: number): void { if (seat === n) { count++; if (first === null) first = atSeat.map((g) => names[g]).join(" "); return; } for (const g of order) { if (seatOf[g] !== -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) const ok = rulesOf[g].every(({ check, a, b }) => seatOf[a] < 0 || seatOf[b] < 0 || check(seatOf[a], seatOf[b])); if (ok) place(seat + 1); seatOf[g] = -1; }}place(1);console.log(count > 0 ? `${count}\n${first}` : "0");
JavaMain.java · 85 行
import java.io.*;import java.util.*;import java.util.function.BiPredicate;public class Main { record Rule(BiPredicate<Integer, Integer> check, int a, int b) {} static int n; static String[] names; static List<List<Rule>> rulesOf = new ArrayList<>(); static Integer[] order; static int[] seatOf, atSeat; static long count = 0; static String first = null; // 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리 static int dist(int sa, int sb) { int d = Math.abs(sa - sb); return Math.min(d, n - d); } static void place(int seat) { if (seat == n) { count++; if (first == null) { StringJoiner sj = new StringJoiner(" "); for (int g : atSeat) sj.add(names[g]); first = sj.toString(); } return; } for (int g : order) { if (seatOf[g] != -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) boolean ok = true; for (Rule r : rulesOf.get(g)) { if (seatOf[r.a()] >= 0 && seatOf[r.b()] >= 0 && !r.check().test(seatOf[r.a()], seatOf[r.b()])) { ok = false; break; } } if (ok) place(seat + 1); seatOf[g] = -1; } } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(in.readLine()); n = Integer.parseInt(st.nextToken()); int m = Integer.parseInt(st.nextToken()); names = in.readLine().trim().split("\\s+"); Map<String, Integer> index = new HashMap<>(); for (int i = 0; i < n; i++) { index.put(names[i], i); rulesOf.add(new ArrayList<>()); } for (int i = 0; i < m; i++) { String[] p = in.readLine().trim().split("\\s+"); // 람다는 effectively final 변수만 가둘 수 있다: k는 반복마다 새로 만든다 final int k = p.length > 3 ? Integer.parseInt(p[3]) : 0; BiPredicate<Integer, Integer> check = switch (p[0]) { case "next" -> (sa, sb) -> dist(sa, sb) == 1; case "apart" -> (sa, sb) -> dist(sa, sb) != 1; case "cw" -> (sa, sb) -> (sa + 1) % n == sb; default -> (sa, sb) -> dist(sa, sb) >= k; }; Rule r = new Rule(check, index.get(p[1]), index.get(p[2])); rulesOf.get(r.a()).add(r); rulesOf.get(r.b()).add(r); } // 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 order = new Integer[n - 1]; for (int i = 1; i < n; i++) order[i - 1] = i; Arrays.sort(order, (g, h) -> names[g].compareTo(names[h])); seatOf = new int[n]; Arrays.fill(seatOf, -1); seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리 atSeat = new int[n]; place(1); System.out.println(count > 0 ? count + "\n" + first : "0"); }}
C#Main.cs · 79 行
using System;using System.Collections.Generic;using System.Linq;class Program{ record Rule(Func<int, int, bool> Check, int A, int B); static int n; static string[] names; static List<Rule>[] rulesOf; static int[] order, seatOf, atSeat; static long count = 0; static string first = null; // 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리 static int Dist(int sa, int sb) { int d = Math.Abs(sa - sb); return Math.Min(d, n - d); } static void Place(int seat) { if (seat == n) { count++; if (first == null) first = string.Join(" ", atSeat.Select(g => names[g])); return; } foreach (int g in order) { if (seatOf[g] != -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) bool ok = rulesOf[g].All(r => seatOf[r.A] < 0 || seatOf[r.B] < 0 || r.Check(seatOf[r.A], seatOf[r.B])); if (ok) Place(seat + 1); seatOf[g] = -1; } } static void Main() { int[] nm = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); n = nm[0]; int m = nm[1]; names = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); var index = new Dictionary<string, int>(); rulesOf = new List<Rule>[n]; for (int i = 0; i < n; i++) { index[names[i]] = i; rulesOf[i] = new List<Rule>(); } for (int i = 0; i < m; i++) { string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int k = p.Length > 3 ? int.Parse(p[3]) : 0; // 반복 몸통 안에서 만든 변수라 람다마다 따로 갇힌다 Func<int, int, bool> check = p[0] switch { "next" => (sa, sb) => Dist(sa, sb) == 1, "apart" => (sa, sb) => Dist(sa, sb) != 1, "cw" => (sa, sb) => (sa + 1) % n == sb, _ => (sa, sb) => Dist(sa, sb) >= k, }; var r = new Rule(check, index[p[1]], index[p[2]]); rulesOf[r.A].Add(r); rulesOf[r.B].Add(r); } // 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 order = Enumerable.Range(1, n - 1).OrderBy(g => names[g], StringComparer.Ordinal).ToArray(); seatOf = Enumerable.Repeat(-1, n).ToArray(); seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리 atSeat = new int[n]; Place(1); Console.WriteLine(count > 0 ? count + "\n" + first : "0"); }}
C++main.cpp · 82 行
#include <algorithm>#include <cstdlib>#include <functional>#include <iostream>#include <map>#include <string>#include <vector>struct Rule { std::function<bool(int, int)> check; int a, b;};int n;std::vector<std::string> names;std::vector<std::vector<Rule>> rulesOf; // 손님마다 그 손님이 나오는 규칙std::vector<int> order, seatOf, atSeat;long long countAll = 0;std::string first;// 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리int dist(int sa, int sb) { int d = std::abs(sa - sb); return std::min(d, n - d);}void place(int seat) { if (seat == n) { if (countAll++ == 0) { for (int i = 0; i < n; i++) first += (i ? " " : "") + names[atSeat[i]]; } return; } for (int g : order) { if (seatOf[g] != -1) continue; seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) bool ok = std::all_of(rulesOf[g].begin(), rulesOf[g].end(), [](const Rule& r) { return seatOf[r.a] < 0 || seatOf[r.b] < 0 || r.check(seatOf[r.a], seatOf[r.b]); }); if (ok) place(seat + 1); seatOf[g] = -1; }}int main() { int m; std::cin >> n >> m; names.resize(n); std::map<std::string, int> index; for (int i = 0; i < n; i++) { std::cin >> names[i]; index[names[i]] = i; } rulesOf.assign(n, {}); for (int i = 0; i < m; i++) { std::string kind, x, y; std::cin >> kind >> x >> y; std::function<bool(int, int)> check; if (kind == "next") check = [](int sa, int sb) { return dist(sa, sb) == 1; }; else if (kind == "apart") check = [](int sa, int sb) { return dist(sa, sb) != 1; }; else if (kind == "cw") check = [](int sa, int sb) { return (sa + 1) % n == sb; }; else { int k; std::cin >> k; check = [k](int sa, int sb) { return dist(sa, sb) >= k; }; // [k]: 지금 값을 복사해 가둔다 } Rule r{check, index[x], index[y]}; rulesOf[r.a].push_back(r); rulesOf[r.b].push_back(r); } // 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 for (int i = 1; i < n; i++) order.push_back(i); std::sort(order.begin(), order.end(), [](int g, int h) { return names[g] < names[h]; }); seatOf.assign(n, -1); seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리 atSeat.assign(n, 0); place(1); std::cout << countAll << '\n'; if (countAll > 0) std::cout << first << '\n';}
Cmain.c · 99 行
#include <stdio.h>#include <stdlib.h>#include <string.h>static int n;/* 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리 */int dist(int sa, int sb) { int d = abs(sa - sb); return d < n - d ? d : n - d;}/* 규칙 검사 함수들: 모양(int, int, int)을 맞춰 두면 함수 포인터 하나로 부를 수 있다 */int rule_next(int sa, int sb, int k) { (void)k; return dist(sa, sb) == 1; }int rule_apart(int sa, int sb, int k) { (void)k; return dist(sa, sb) != 1; }int rule_cw(int sa, int sb, int k) { (void)k; return (sa + 1) % n == sb; }int rule_far(int sa, int sb, int k) { return dist(sa, sb) >= k; }typedef struct { int (*check)(int, int, int); /* 함수 포인터 */ int a, b, k;} Rule;static char names[9][16];static Rule rules[20];static int rules_of[9][20], nrules_of[9]; /* 손님마다 그 손님이 나오는 규칙 번호 */static int order[9], seat_of[9], at_seat[9];static long count = 0;static char first[200];int find(const char *s) { for (int i = 0; i < n; i++) if (strcmp(names[i], s) == 0) return i; return -1;}void place(int seat) { if (seat == n) { if (count++ == 0) { first[0] = '\0'; for (int i = 0; i < n; i++) { if (i) strcat(first, " "); strcat(first, names[at_seat[i]]); } } return; } for (int oi = 0; oi < n - 1; oi++) { int g = order[oi]; if (seat_of[g] != -1) continue; seat_of[g] = seat; at_seat[seat] = g; /* 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) */ int ok = 1; for (int j = 0; j < nrules_of[g] && ok; j++) { Rule *r = &rules[rules_of[g][j]]; if (seat_of[r->a] >= 0 && seat_of[r->b] >= 0 && !r->check(seat_of[r->a], seat_of[r->b], r->k)) ok = 0; } if (ok) place(seat + 1); seat_of[g] = -1; }}int by_name(const void *x, const void *y) { return strcmp(names[*(const int *)x], names[*(const int *)y]);}int main(void) { int m; scanf("%d %d", &n, &m); for (int i = 0; i < n; i++) scanf("%15s", names[i]); for (int i = 0; i < m; i++) { char kind[8], x[16], y[16]; scanf("%7s %15s %15s", kind, x, y); Rule *r = &rules[i]; r->a = find(x); r->b = find(y); r->k = 0; if (strcmp(kind, "next") == 0) r->check = rule_next; else if (strcmp(kind, "apart") == 0) r->check = rule_apart; else if (strcmp(kind, "cw") == 0) r->check = rule_cw; else { r->check = rule_far; scanf("%d", &r->k); } rules_of[r->a][nrules_of[r->a]++] = i; rules_of[r->b][nrules_of[r->b]++] = i; } /* 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다 */ for (int i = 1; i < n; i++) order[i - 1] = i; qsort(order, n - 1, sizeof(int), by_name); for (int i = 0; i < n; i++) seat_of[i] = -1; seat_of[0] = 0; /* 처음 적힌 손님은 늘 0번 자리 */ at_seat[0] = 0; place(1); printf("%ld\n", count); if (count > 0) printf("%s\n", first); return 0;}
Craykonmain.cray · 127 行
// 둥근 탁자에서 두 자리 사이의 짧은 쪽 거리거리(sa, sb){ d = 数学.绝对值(sa - sb); 返回 数学.较小值(d, n - d);}// 규칙 검사 함수들. 크레이콘에는 람다가 없으니 모양(sa, sb, k)을 맞춘 함수를 이름으로 넘긴다이웃(sa, sb, k){ 返回 거리(sa, sb) == 1;}떨어짐(sa, sb, k){ 返回 거리(sa, sb) != 1;}시계방향(sa, sb, k){ 返回 (sa + 1) % n == sb;}멀리(sa, sb, k){ 返回 거리(sa, sb) >= k;}// 이름 순 비교(정렬 기준 함수)이름순(g, h){ 如果 (names[g] < names[h]) { 返回 -1; } 返回 1;}앉히기(seat){ 如果 (seat == n) { count += 1; 如果 (count == 1) { first = names[atSeat[0]]; 循环 (s = 1; s < n; s++) { first += " " + names[atSeat[s]]; } } 返回; } 遍历 (g 在 order) { 如果 (seatOf[g] == -1) { seatOf[g] = seat; atSeat[seat] = g; // 둘 다 앉은 규칙만 바로 검사해서, 어긋나면 더 앉히지 않는다(가지치기) ok = 真; 遍历 (r 在 rulesOf[g]) { sa = seatOf[r[1]]; sb = seatOf[r[2]]; 如果 (sa >= 0 && sb >= 0 && !r[0](sa, sb, r[3])) { ok = 假; 跳出; } } 如果 (ok) { 앉히기(seat + 1); } seatOf[g] = -1; } }}nm = 控制台.读数字();n = nm[0];m = nm[1];names = 控制台.读行().去空白().分割(" ");index = 字典();rulesOf = [];循环 (i = 0; i < n; i++){ index[names[i]] = i; rulesOf.添加([]);}checks = 字典(); // 규칙 이름 → 검사 함수checks["next"] = 이웃;checks["apart"] = 떨어짐;checks["cw"] = 시계방향;checks["far"] = 멀리;循环 (i = 0; i < m; i++){ p = 控制台.读行().去空白().分割(" "); kval = 0; 如果 (p.数量 > 3) { kval = p[3].转数字(); } rule = [checks[p[0]], index[p[1]], index[p[2]], kval]; // [검사 함수, a, b, k] rulesOf[rule[1]].添加(rule); rulesOf[rule[2]].添加(rule);}// 이름 순으로 앉혀 보면 처음 찾은 배치가 사전 순으로 가장 앞선다order = [];循环 (i = 1; i < n; i++){ order.添加(i);}order.排序(이름순);seatOf = 新列表(n, -1);seatOf[0] = 0; // 처음 적힌 손님은 늘 0번 자리atSeat = 新列表(n, 0);count = 0;first = "";앉히기(1);控制台.输出(count);如果 (count > 0){ 控制台.输出(first);}