Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

35-Munbin-Lee #140

Merged
merged 2 commits into from
Feb 25, 2024
Merged

35-Munbin-Lee #140

merged 2 commits into from
Feb 25, 2024

Conversation

Munbin-Lee
Copy link
Member

@Munbin-Lee Munbin-Lee commented Feb 18, 2024

πŸ”— 문제 링크

https://www.acmicpc.net/problem/24891

βœ”οΈ μ†Œμš”λœ μ‹œκ°„

2μ‹œκ°„

✨ μˆ˜λ„ μ½”λ“œ

λ¨Όμ € 브루트포슀 풀이λ₯Ό μƒκ°ν•΄λ³΄μž.

λͺ¨λ“  경우의 단어 μˆœμ—΄μ„ κ΅¬ν•˜λ €λ©΄ $_N\mathrm{P}_L$ 의 μ‹œκ°„μ΄ ν•„μš”ν•˜λ‹€.

각 단어 μˆœμ—΄μ— λŒ€ν•˜μ—¬, 단어 λ§ˆλ°©μ§„μΈμ§€ ν™•μΈν•˜λ €λ©΄ $L^2$ 의 μ‹œκ°„μ΄ ν•„μš”ν•˜λ‹€.

λ”°λΌμ„œ, 브루트포슀 μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” $O(_N\mathrm{P}_L L^2)$ = 20 * 19 * 18 * 17 * 16 * 5 * 5 = 46512000 μ΄λ―€λ‘œ μ‹œκ°„ 내에 톡과할 수 μžˆλ‹€.

파이썬의 itertools.permutaions둜 λ‚ λ¨Ήν•΄λ³΄μž.

from itertools import permutations

stdin = open(0)

L, N = map(int, stdin.readline().split())
words = stdin.read().splitlines()

# 단어 μˆœμ—΄ xκ°€ 단어 λ§ˆλ°©μ§„μΈμ§€ ν™•μΈν•˜λŠ” ν•¨μˆ˜
def isValid(x):
    for i in range(L):
        for j in range(L):
            if x[i][j] != x[j][i]: return False
    
    return True

answer = ('a',)

for perm in permutations(words, L):
    if not isValid(perm): continue
    
    answer = min(answer, perm)

if len(answer) == 1:
    print('NONE')
    exit()

print(*answer, sep='\n')

image

무지성 λΈŒλ£¨νŠΈν¬μŠ€λ‘œλ„ μΆ©λΆ„νžˆ 톡과할 수 μžˆλ‹€.


사싀 λ‚œ μ²˜μŒμ—λŠ” λ°±νŠΈλž˜ν‚ΉμœΌλ‘œ λ¨Όμ € ν’€λ €κ³  ν–ˆλ‹€.

단어듀을 사전 순으둜 μ •λ ¬ν•˜κ³ , BFS둜 제일 λ¨Όμ € 탐색에 μ„±κ³΅ν•œ 단어 λ§ˆλ°©μ§„μ΄ 닡일 것이라고 μƒκ°ν–ˆλ‹€.

ν•˜μ§€λ§Œ ν‹€λ Έλ‹€.

κ·Έλž˜μ„œ BFS둜 κ·Έλƒ₯ λͺ¨λ“  단어 λ§ˆλ°©μ§„μ„ λ°±νŠΈλž˜ν‚Ή νƒμƒ‰ν•˜μ˜€λ‹€.

#include <iostream>
#include <vector>
#include <tuple>
#include <queue>

using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int L, N;
    cin >> L >> N;

    vector<string> words(N);

    for (auto &word: words) {
        cin >> word;
    }

    queue<tuple<int, int, vector<vector<char>>>> q;
    vector<vector<char>> init(L, vector<char>(L));
    q.emplace(0, 0, init);

    vector<vector<char>> answer = {{'Z' + 1}};

    while (!q.empty()) {
        auto [index, mask, cur] = q.front();
        q.pop();

        auto isValid = [&](int i) {
            for (int j = 0; j < L; j++) {
                if (!cur[index][j]) continue;
                if (cur[index][j] != words[i][j]) return false;
            }

            return true;
        };

        for (int i = 0; i < N; i++) {
            if (mask & (1 << i)) continue;
            if (!isValid(i)) continue;

            auto next = cur;

            for (int j = 0; j < L; j++) {
                next[index][j] = words[i][j];
                next[j][index] = words[i][j];
            }

            if (index + 1 == L) {
                answer = min(answer, next);
                continue;
            }

            q.emplace(index + 1, mask | (1 << i), next);
        }
    }

    if (answer.size() == 1) {
        cout << "NONE";
        return 0;
    }

    for (auto &word: answer) {
        for (char ch: word) {
            cout << ch;
        }
        cout << '\n';
    }

    return 0;
}

image

C++인 것을 κ°μ•ˆν–ˆμ„ λ•Œ, 브루트포슀(pypy3)와 λ°±νŠΈλž˜ν‚Ή(C++)의 μ‹œκ°„ 차이가 μ–Όλ§ˆ λ‚˜μ§€ μ•ŠλŠ”λ‹€.


그럼 μ–΄λ–»κ²Œ 효율적으둜 ν’€ 수 μžˆμ„κΉŒ?

단어λ₯Ό μ •λ ¬ν•˜κ³ , bfs λŒ€μ‹  dfsλ₯Ό λŒλ €μ„œ μ²˜μŒμ— λ‚˜μ˜€λŠ” 단어 λ§ˆλ°©μ§„μ„ 좜λ ₯ν•˜μ˜€λ”λ‹ˆ λ§žμ•˜λ‹€.

stdin = open(0)

L, N = map(int, stdin.readline().split())
words = sorted(stdin.read().splitlines())

def isValid(x):
    for i in range(L):
        for j in range(L):
            if x[i][j] != x[j][i]: return False
    
    return True

def dfs(index, mask, cur):
    if index == L:
        if not isValid(cur): return
        
        print(*cur, sep='\n')
        exit()
    
    for i in range(N):
        if mask & (1 << i): continue
        dfs(index + 1, mask | (1 << i), cur + [words[i]])

dfs(0, 0, [])

print('NONE')

image

μ‹œκ°„μ΄ 절반 κ°€λŸ‰μœΌλ‘œ μ€„μ–΄λ“€μ—ˆλ‹€.

indexκ°€ λ§ˆμ§€λ§‰μΌ λ•Œλ§Œ μ²΄ν¬ν•˜μ§€ 말고, 쀑간 쀑간에 λ‹¨μ–΄λ§ˆλ°©μ§„μΈμ§€ μ²΄ν¬ν•˜μ—¬ 브루트포슀->λ°±νŠΈλž˜ν‚ΉμœΌλ‘œ λ°”κΎΈλ©΄ 훨씬 더 빨라질 것이닀.


μ™œ BFSκ°€ μ•„λ‹ˆλΌ DFSλ₯Ό λŒλ €μ•Όν• κΉŒ?

λͺ¨λ₯΄κ² λ‹€.


그런데, itertools.permutations의 탐색 μˆœμ„œλ₯Ό μƒκ°ν•΄λ³΄λ‹ˆ dfs의 탐색 μˆœμ„œμ™€ κ°™λ‹€.

그럼 κ·Έλƒ₯ dfsλ₯Ό κ΅¬ν˜„ν•˜μ§€ 말고 첫번째 perm을 좜λ ₯ν•˜λ©΄ λ˜λŠ” 것 μ•„λ‹Œκ°€?

from itertools import permutations

stdin = open(0)

L, N = map(int, stdin.readline().split())
words = sorted(stdin.read().splitlines())

# 단어 μˆœμ—΄ xκ°€ 단어 λ§ˆλ°©μ§„μΈμ§€ ν™•μΈν•˜λŠ” ν•¨μˆ˜
def isValid(x):
    for i in range(L):
        for j in range(L):
            if x[i][j] != x[j][i]: return False
    
    return True

for perm in permutations(words, L):
    if not isValid(perm): continue
    
    print(*perm, sep='\n')
    exit()

print('NONE')

image

permutations νŠΉμ„± 상 μ΅œμ ν™”κ°€ λ˜μ–΄μžˆμ–΄μ„œ μ„Έ 번째 ν’€μ΄λ³΄λ‹€λŠ” 살짝 λΉ λ₯΄λ‹€.

@9kyo-hwang
Copy link

image
γ„·γ„·γ„·γ„·γ„·γ„·γ„·γ„·

@Munbin-Lee Munbin-Lee marked this pull request as ready for review February 19, 2024 14:40
Copy link
Member

@tgyuuAn tgyuuAn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import sys

word_length, word_count = map(int,sys.stdin.readline().split())
answer = []
word_list = []
for _ in range(word_count):
    word_list.append(sys.stdin.readline())

def is_magic_square(idx_bundle):
    for col in range(len(idx_bundle)):
        for row in range(len(idx_bundle)):
            if word_list[idx_bundle[row]][col] != word_list[idx_bundle[col]][row]: return False
    return True

def dfs(idx_bundle, visited, word_count, word_length):
    global answer

    if len(idx_bundle) == word_length:
        if is_magic_square(idx_bundle):
            magic_square = ""
            for idx in idx_bundle:
                magic_square += word_list[idx]
            answer.append(magic_square)
        return

    for idx in range(word_count):
        if idx in visited: continue

        visited.add(idx)
        idx_bundle.append(idx)
        dfs(idx_bundle, visited,word_count, word_length)
        visited.discard(idx)
        idx_bundle.pop()
    return

dfs(list(), set(), word_count, word_length)
answer.sort()
if answer: print(answer[0])
else: print("NONE")

μ €λŠ” μ™„νƒμœΌλ‘œ ν’€μ—ˆμ”λ‹ˆλ‹€.

근데 μ‹œκ°„μ΄ λ„ˆλ¬΄ 였래 κ±Έλ €μ„œ λ¬ΈλΉˆλ‹˜ μ½”λ“œ λ³΄λ‹ˆκΉŒ μž…μ΄ 쩍쩍 λ²Œμ–΄μ§€λ„€μš”

문제 μ˜λ„λŠ” 완탐인 것 같은데 파이썬 permutations 으둜 μ ‘κ·Όν•˜λŠ” 아이디어 무릎 탁 μ³€κ³ 

μ •λ ¬ν•΄μ„œ 맨 처음 κΊΌ μ œμΆœν•˜λŠ” κ±°μ—μ„œ λ¬΄λ¦Žμ„ 탁탁 μ³€λ„€μš” γ…Žγ„·γ„·;;

Comment on lines +6 to +20
words = sorted(stdin.read().splitlines())

# 단어 μˆœμ—΄ xκ°€ 단어 λ§ˆλ°©μ§„μΈμ§€ ν™•μΈν•˜λŠ” ν•¨μˆ˜
def isValid(x):
for i in range(L):
for j in range(L):
if x[i][j] != x[j][i]: return False

return True

for perm in permutations(words, L):
if not isValid(perm): continue

print(*perm, sep='\n')
exit()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와 단어λ₯Ό μ •λ ¬ν•œ 뒀에

permutations으둜 처음 λ‚˜μ˜€λŠ” κ±°λ₯Ό μ œμΆœν•˜λ©΄ 완탐할 ν•„μš”λ„ 없이

처음 κ±Έλ¦¬λŠ” κ±°μ—μ„œ λ°”λ‘œ μ œμΆœν•˜λ©΄ λ˜λ‹ˆκΉŒ

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

μ§€λ¦¬λŠ”λ°μš”..

Copy link
Member Author

@Munbin-Lee Munbin-Lee Feb 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

근데 μ™œ 처음 것이 λ‹΅μΈμ§€λŠ” λͺ¨λ¦„μš”.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

근데 μ™œ 처음 것이 λ‹΅μΈμ§€λŠ” λͺ¨λ¦„μš”.

μ›λž˜λŠ” λͺ¨λ“  경우의 수λ₯Ό κ΅¬ν•΄μ„œ ꡬ해진 μ •λ‹΅ ν›„λ³΄μžλ“€μ—μ„œ μ •λ ¬ν•΄μ„œ 첫 번째 κΊΌλ₯Ό μ œμΆœν•΄μ•Όν•˜λŠ”λ° (사전 순으둜)

근데 μ–΄μ°¨ν”Ό μ •λ ¬ ν•œ 뒀에 κ°€μž₯ 첫 번째 λ‚˜μ˜€λŠ” μΉœκ΅¬λŠ” μ •λ ¬λœ μƒνƒœμ—μ„œ λ½‘μ•˜κΈ° λ•Œλ¬Έμ— μ–΄μ°¨ν”Ό 사전에 첫 번째 μˆœμ„œμΈ κ±°μ£ ...

κ°œλ˜‘λ˜‘ν•œλ°μš”?

@pknujsp
Copy link
Collaborator

pknujsp commented Feb 20, 2024

이 문제 μž¬λ°Œλ„€μš”
ν•œ μ‹œκ°„ λ„˜κ²Œ 걸리긴 ν–ˆλŠ”λ°
쀑간에 μ •λ ¬ν•˜κ³  μˆœμ„œλŒ€λ‘œ dfsμ§„ν–‰ν•˜λ‹€κ°€ 쑰건맞으면 좜λ ₯ν•˜κ³  μ’…λ£Œν•˜λŠ” κ±Έ μƒκ°λ‚˜μ„œ
λ°”λ‘œ ν’€λ Έλ„€μš”

λΉ„μŠ·ν•œ 문제 λ°”λ‘œ ν’€μ–΄λ³΄λŸ¬ κ°‘λ‹ˆλ‹€

from sys import *
from collections import *

stdin = open('단어 λ§ˆλ°©μ§„.txt')

L, N = map(int, stdin.readline().split())
words = [stdin.readline().strip() for _ in range(N)]
words.sort()

def check(arr):
    length = len(arr)
    if length == 2:
        if arr[0][1] == arr[1][0]:
            return True
        return False

    for x in range(length):
        for c in range(x + 1, length):
            if arr[x][c] != arr[c][x]:
                return False

    return True

def dfs(result, indices, words):
    if len(indices) == L:
        for r in range(L):
            for c in range(L):
                if result[r][c] != result[c][r]:
                    return
        for word in result:
            print(word)
        exit()

    for i in range(N):
        if i not in indices:
            indices.add(i)

            result.append(words[i])
            dfs(result, indices, words)

            result.pop()
            indices.remove(i)

t_result = deque()
dfs(t_result, set(), words)

print('NONE')

@yuna83
Copy link
Member

yuna83 commented Feb 25, 2024

for perm in permutations(words, L):
permutation에 λŒ€ν•΄μ„œ 까먹고 μžˆμ—ˆλŠ”λ° λ‹€μ‹œ μ΅ν˜€κ°€μš”..!!
풀이방법에 λŒ€ν•΄μ„œ μ™„μ „νžˆ μ΄ν•΄ν•˜κ³  μžˆμœΌλ‹ˆ λ‹€μ–‘ν•œ 풀이법을 μ‹œλ„ν•΄λ³΄λŠ”κ²ƒ 짱 λ©‹μ§€μ‹­λ‹ˆλ‹€!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants