{ }codelper
暴力枚举高阶函数P0184

圆桌座位规则

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
输入(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 sys  def 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);}