SDK does not contain 'libarclite' at the path '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphonesimulator.a'; try increasing the minimum deployment target
podfile 내 platform 관련 코드도 주석 해제 해제 후 11.0으로 변경해주고,
iOS Deployment Target 값도 13.0으로 변경해줬음
그리고 실행했더니 냅다 또 오류 4개 추가로 뜸
Sandbox: rsync.samba(59873) deny(1) ...(생략)
찾아보니 아래와 같이 Build Setting 내 "User Script Sandboxing"의 값을 Yes -> No 로 변경하면 실행 성공함
HTTP (HyperText Transfer Protocol)는 클라이언트와 서버 간 통신 규약을 나타내는 것임
그 중 Status Code는 서버가 (클라이언트로부터 받은) 요청에 대한 처리 결과를 나타내기 위한 숫자로, 응답 메세지의 상태 라인에 포함됨
// 서버의 응답 메세지 예시 //
HTTP/1.1 200 OK // -> 200이라는 상태 코드를 통해 요청 처리 성공을 전달
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html
<!DOCTYPE html... (here comes the 29769 bytes of the requested web page
HTTP Status Code는 IANA라는 인터넷 할당 번호 관리 기관에서 "HTTP Status Code Registry"라는 이름으로 관리
클라이언트의 요청을 받았으며, 요청 처리를 진행 중 (1xx 계열의 응답은 HTTP/1.1 클라이언트에게만 보낼 수 있으며 응답은 바디 없이 상태 라인, 헤더(생략 가능), 빈 줄로 종료)
100
Continue
계속 진행 (클라이언트는 요청 헤더에 ‘Expect: 100-continue’를 보내고 서버는 이를 처리할 수 있으면 이 코드로 응답)
101
Switching Protocols
프로토콜을 전환해야함 (프로토콜을 HTTP 1.1에서 업그레이드할 때 Upgrade 응답 헤더에 표시. 현재는 HTTP 1.1이 최신이므로 사용할 일이 없음)
102
Processing
(WebDAV) 처리 중이다. (서버가 처리하는 데 오랜 시간이 예상되어 클라이언트에서 타임 아웃이 발생하지 않도록 이 응답 코드를 보냄)
2NN - 요청 처리 성공
클라이언트가 요청한 동작을 수신하여 성공적으로 처리함
200
OK
서버가 요청을 성공적으로 처리
201
Created
요청이 처리되어서 새로운 리소스가 생성 (응답 헤더 Location에 새로운 리소스의 절대 URI를 기록)
202
Accepted
요청은 접수하였지만, 처리가 완료되지 않음 (응답 헤더의 Location, Retry-After를 참고하여 클라이언트는 다시 요청을 보냄)
203
Non-Authoritative Information
응답 헤더가 오리지널 서버로부터 제공된 것이 아님 (프록시 서버가 응답 헤더에 주석을 덧붙인 경우가 하나의 예)
204
No Content
처리를 성공하였지만, 클라이언트에게 돌려줄 콘텐츠가 없음 (응답에는 헤더만 있고 바디는 없음. DELETE 요청에 대한 응답에 많이 사용됨)
205
Reset Content
처리를 성공하였고 화면을 리셋 (예를 들어 브라우저가 입력 폼을 보여 주고 있을 때 이 응답 코드를 받으면 브라우저는 모든 입력 항목을 리셋하고 재입력할 수 있는 상태가 됨)
206
Partial Content
콘텐츠의 일부만을 보냄 (응답 헤더의 Content-Range에 응답 콘텐츠의 범위를 기록. 예를 들어 1,500 바이트의 리소스 중에서 처음의 500바이트만을 보낼 때 사용할 수 있음.)
207
Multi-Status
(WebDAV) 처리 결과의 스테이터스가 여러 개임 (207 응답은 성공을 뜻하지만, 각각의 처리 결과가 성공인지는 바디를 봐야 알 수 있음)
3NN - 리다이렉션 (Redirection)
클라이언트는 요청을 마치기 위해 추가 동작을 취해야 함
300
Multiple Choices
선택 항목이 여러 개가 있음 (지정한 URI에 대해서 콘텐츠 협상을 수행한 결과, 서버에서 콘텐츠를 결정하지 못하고 클라이언트에게 복수 개의 링크를 응답할 때 사용)
301
Moved Permanently
지정한 리소스가 새로운 URI로 이동함 (이동할 곳의 새로운 URI는 응답 헤더 Location에 기록)
302
Found
요청한 리소스를 다른 URI에서 찾음 (요청한 URI가 없으므로 클라이언트 메소드를 그대로 유지한 채, 응답 헤더 Location에 표시된 다른 URI로 요청을 재송신할 필요가 있음.) * 302의 의미를 정확하게 개선해서 307을 정의하였으므로 이 응답 코드의 사용은 권장 X
303
See Other
다른 위치로 요청해야함 (요청에 대한 처리 결과를 응답 헤더 Location에 표시된 URI에서 GET으로 취득할 수 있음. 브라우저의 폼 요청을 POST로 처리하고, 그 결과 화면으로 리다이렉트시킬 때 자주 사용하는 응답 코드임)
304
Not Modified
마지막 요청 이후 요청한 페이지는 수정되지 않음 (If-Modified-Since와 같은 조건부 GET 요청일 때 지정한 리소스가 갱신되지 않았음을 알려줌. 이 응답 코드에는 바디가 없음)
임시로 리다이렉션 요청이 필요함 (요청한 URI가 없으므로 클라이언트 메소드를 그대로 유지한 채 응답 헤더 Location에 표시된 다른 URI로 요청을 재송신해야함. 클라이언트는 향후 요청 시 원래 위치를 계속 사용해야 함.) * 302의 의미를 정확하게 재정의해서 HTTP/1.1의 307 응답으로 추가
4NN - 클라이언트 오류
클라이언트의 요청에 오류가 있음 (자주 사용되는 상태 코드 : 400, 401, 403, 404)
400
Bad Request
요청의 구문이 잘못됨 (클라이언트가 모르는 4xx 계열 응답 코드가 반환된 경우에도 클라이언트는 400과 동일하게 처리하도록 규정)
401
Unauthorized
지정한 리소스에 대한 액세스 권한이 없음 (응답 헤더 WWW-Authenticate에 필요한 인증 방식을 지정)
402
Payment Required
지정한 리소스를 액세스하기 위해서는 결제가 필요함 * 이 응답 코드는 실제로는 사용되지 않음
403
Forbidden
지정한 리소스에 대한 액세스가 금지됨 (401 인증 처리 이외의 사유로 리소스에 대한 액세스가 금지되었음을 의미. 리소스의 존재 자체를 은폐하고 싶은 경우도 404 응답 코드를 사용할 수 있음.)
404
Not Found
지정한 리소스를 찾을 수 없음
405
Method Not Allowed
요청한 URI가 지정한 메소드를 지원하지 않음 (응답 헤더 Allow에 이 URI가 지원하는 메소드 목록을 기록함)
406
Not Acceptable
클라이언트가 Accept-* 헤더에 지정한 항목에 관해 처리할 수 없음 (응답 바디에는 300 응답처럼 서버가 수용 가능한 다른 선택지 리스트가 기록됨)
407
Proxy Authentication Required
클라이언트는 프록시 서버에 인증이 필요함 (프록시 서버의 응답 헤더 Proxy-Authenticate에 필요한 인증 방식을 지정)
408
Request Timeout
요청을 기다리다 서버에서 타임아웃함
409
Conflict
서버가 요청을 수행하는 중에 충돌이 발생함 (예를 들어 사용자명을 new_name으로 변경하려 하였지만, 서버에 이미 new_name이라는 사용자가 존재하는 경우. 응답 헤더 Location에는 충돌이 발생한 리소스의 URI를 기록함)
410
Gone
지정한 리소스가 이전에는 존재하였지만, 현재는 존재하지 않음 (예를 들어 기간이 한정된 프로모션 사이트가 사라진 경우 사용할 수 있음)
411
Length Required
요청 헤더에 Content-Length를 지정해야 함
412
Precondition Failed
If-Match와 같은 조건부 요청에서 지정한 사전 조건이 서버와 맞지 않음
413
Request Entity Too Large
요청 메시지가 너무 큼 (서버는 접속을 끊음)
414
Request-URI Too Large
요청 URI가 너무 긺
415
Unsupported Media Type
클라이언트가 지정한 미디어 타입을 서버가 지원하지 않음 (예를 들어 서버가 지원하는 이미지는 JPG, PNG뿐인데 클라이언트가 GIF 형식의 이미지를 요청하는 경우)
416
Range Not Satisfiable
클라이언트가 지정한 리소스의 범위가 서버의 리소스 사이즈와 맞지 않음
417
Expectation Failed
클라이언트가 지정한 Expect 헤더를 서버가 이해할 수 없음
422
Unprocessable Entity
(WebDAV) 클라이언트가 송신한 XML이 구문은 맞지만, 의미상 오류가 있음
423
Locked
(WebDAV) 지정한 리소스는 잠겨있음
424
Failed Dependency
(WebDAV) 다른 작업의 실패로 인해 본 요청도 실패함
426
Upgraded Required
클라이언트의 프로토콜의 업그레이드가 필요함 (응답에 Upgrade 헤더를 보내 필요한 프로토콜을 알려 줌)
428
Precondition Required
If-Match와 같은 사전조건을 지정하는 헤더가 필요함. (If-Match 헤더가 있지만, 맞지 않는 경우는 412 응답을 보냄)
429
Too Many Requests
클라이언트가 주어진 시간 동안 너무 많은 요청을 보냄 (요청의 속도를 제한할 때 사용. 응답에 Retry-After 헤더를 보내 얼마나 기다릴지를 알려 줄 수 있음)
431
Request Header Fields Too Large
헤더의 길이가 너무 큼 (헤더의 전체 크기가 크거나 또는 하나의 헤더가 매우 큰 경우. 보통 Referer URL이 길거나 쿠키 항목이 많은 경우)
444
Connection Closed Without Response
(NGINX) 응답을 보내지 않고 연결을 종료함 (보통 악의적인 요청에 대해서 사용하며, 클라이언트에서는 응답을 볼 수 없고 Nginx 로그에 나타남)
451
Unavailable For Legal Reasons
법적으로 문제가 있는 리소스를 요청
5NN - 서버 오류
서버에 오류가 발생하여 요청 처리에 실패
500
Internal Server Error
서버에 오류 발생 (클라이언트가 모르는 5xx 계열의 응답 코드가 반환된 경우에도 클라이언트는 500과 동일하게 처리하도록 규정)
501
Not Implemented
요청한 URI의 메소드에 대해 서버가 구현하고 있지 않음
502
Bad Gateway
게이트웨이 또는 프록시 역할을 하는 서버가 그 뒷단의 서버로부터 잘못된 응답을 받음
503
Service Unavailable
현재 서버에서 서비스를 제공할 수 없음 (보통은 서버의 과부하나 서비스 점검 등 일시적인 상태)
504
Gateway Timeou
게이트웨이 또는 프록시 역할을 하는 서버가 그 뒷단의 서버로부터 응답을 기다리다 타임아웃이 발생
상하좌우로 연속된 장애물 구역의 총 개수와 각 장애물 구역 내의 장애물 개수를 오름차순으로 출력
풀이법 구상
기본 DFS/BFS를 통한 탐색 문제
코드 구현 (자바 사용)
import java.io.*;
import java.util.*;
publicclassMain{
publicstaticvoidmain(String[] args)throws IOException {
// 입력받기
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[][] map = newint[N][N];
for(int i=0; i<N; i++) {
char[] input = br.readLine().toCharArray();
for(int j=0; j<N; j++) map[i][j] = Character.getNumericValue(input[j]);
}
// BFS를 활용한 블록 탐색
ArrayList<Integer> block = new ArrayList<>();
boolean[][] ch = newboolean[N][N]; // 방문 여부 확인용(방문O - true / 방문X - false)
Queue<int[]> q = new LinkedList<>();
int[] dx = {-1,0,1,0};
int[] dy = {0,1,0,-1};
for(int i=0; i<N; i++) {
for(int j=0; j<N; j++) {
if(map[i][j] == 1 && !ch[i][j]) {
int cnt = 1; // 장애물 개수
q.offer(newint[]{i,j});
ch[i][j] = true;
while(!q.isEmpty()) {
int[] cur = q.poll();
for(int d=0; d<4; d++) {
int nx = cur[0] + dx[d];
int ny = cur[1] + dy[d];
if(nx < 0 || nx >= N || ny < 0 || ny >= N) continue; // 지도 범위를 벗어난 경우if(map[nx][ny] == 0) continue; // 도로인 경우if(map[nx][ny] == 1 && ch[nx][ny]) continue; // 이미 방문한 장애물일 경우
q.offer(newint[]{nx,ny});
ch[nx][ny] = true;
cnt++;
}
}
block.add(cnt);
}
}
}
// 결과 출력
Collections.sort(block);
System.out.println(block.size());
for(int b : block) System.out.println(b);
}
}
코드 구현 (파이썬 사용)
defdfs(x,y):if x<0or x>=n or y<0or y>=n: returnFalseif arr[x][y] == 1:
sum.append(1) # 연속된 구역 내 장애물 개수 +1
arr[x][y] = 0# 방문처리# 상하좌우 탐색
dfs(x,y+1)
dfs(x,y-1)
dfs(x-1,y)
dfs(x+1,y)
returnTruereturnFalse
n = int(input())
arr = []
for _ inrange(0,n): arr.append(list(map(int, input())))
sum = [] # 연속된 구역 내 장애물 개수를 추가할 배열
sum_arr = []
for p inrange(0,n):
for q inrange(0,n):
if dfs(p,q) == True:
sum_arr.append(len(sum)) # 연속된 하나의 구역을 탐색한 후, 구역 내 장애물 개수를 결과에 추가sum = [] # 새로운 연속된 구역 내 장애물 개수를 파악하기 위해 초기화
sum_arr.sort()
print(len(sum_arr))
for i inrange(0,len(sum_arr)): print(sum_arr[i])
- 같은 글자로 구성된 쌍은 사이에 'X'를 끼워주는데, 'XX'는 끼워줘봤자 여전히 중복이므로 'Q'를 끼워줌
- 가장 최종적으로 나온 쌍들 중 마지막이 1개 문자로 이루어졌다면 끝에 'X' 추가 (XX가 되어도 무관함)
각 쌍에 대해 입력받은 키값을 참고하여 다른 글자로 바꾸어줘야하는데, 참고할 키값은 길이와 상관없이 아래와 같은 규칙으로 5*5의 형태로 변형해야함
- 입력받은 키값을 차례로 돌면서 (0,0)자리부터 한 글자씩 채워줌
- 단, 이미 이전에 등장한 적이 있는 글자가 또 나오면 건너뜀
- 입력받은 키값을 이용해 채웠는데 25자리를 모두 채우지 못 한 경우, 알파벳 중 안 쓴 걸 가져다가 채우면 됨
풀이법 구상
문제가 아주 길어서 이해하는데 시간이 좀 걸렸음
문제를 풀어나갈 순서를 아래처럼 정리하면 크게 복잡한 논리를 요구하지는 않아보임
1. 메세지/키 입력받기 2. 2글자 쌍으로 나누기 3. 입력받은 키를 5*5의 형태로 변경 4. 쌍마다 암호화 (1) 암호판의 같은 행에 존재하는 쌍이면 우측 한 칸씩 밀어서 (2) 같은 행에 존재하지 않고 같은 열에 존재하면 아래로 한 칸씩 밀어서 (3) 서로 다른 행/열에 존재하는 경우 서로의 열값을 바꾼 위치로
코드구현 (파이썬사용)
### 중복되는 글자쌍이 없도록 메세지 수정하는 메소드defgetPair(input):# 우선 2자씩 쪼개서 확인# 같은 글자로 구성된 쌍은 사이에 'X'를 끼워주는데, 글자쌍이 'XX'인 경우에는 'Q'추가# 가장 최종적으로 나온 쌍들 중 마지막이 1개 문자로 이루어졌다면 끝에 'X' 추가 (XX가 되어도 무관함)
result = inputwhile isDuplicated(result): result = setNotDuplicated(result) # 중복되는 쌍이 없을 때까지 반복iflen(result)%2 == 1: result += 'X'return result
### 중복되는 글자쌍이 존재하는지 확인하는 메소드defisDuplicated(str):for i inrange(0,len(str)-1,2):
ifstr[i] == str[i+1]: returnTruereturnFalse### 중복되는 글자쌍 사이에 'X' 혹은 'Q'를 추가하는 메소드defsetNotDuplicated(str):
str_list = list(str)
for i inrange(0,len(str)-1,2):
if str_list[i] == str_list[i+1]:
str_list.insert(i+1, 'X'if str_list[i] != 'X'else'Q')
return''.join(str_list)
### 입력된 키값을 기반으로 5*5 크기의 암호판을 만드는 메소드defgetKey(input_key):# 입력받은 키값을 차례로 돌면서 (0,0)자리부터 한 글자씩 채워줌# 단, 이미 이전에 등장한 적이 있는 글자가 또 나오면 건너뜀# 입력받은 키값을 이용해 채웠는데 25자리를 모두 채우지 못 한 경우, 알파벳 중 안 쓴 걸 가져다가 채우면 됨
alphabet_list = [chr(i) for i inrange(ord('A'),ord('Z')+1)]
alphabet_list.remove('J')
key_arr = []
# 우선 입력받은 키값으로 배열 채우기for k in input_key:
iflen(key_arr) == 25: breakif k in alphabet_list:
key_arr.append(k)
alphabet_list.remove(k)
# 배열 길이가 25 미만이면 안 쓴 알파벳 사용iflen(key_arr) < 25:
for a in alphabet_list:
iflen(key_arr) == 25: break
key_arr.append(a)
# 1차원 배열 값을 토대로 2차원 암호판 구성 후 반환# result_key = [[0] * 5] * 5 # 얕은 복사로 인해 값 변경에 오류 발생
result_key = [[0for p inrange(5)] for q inrange(5)]
for p inrange(0,5):
for q inrange(0,5): result_key[p][q] = key_arr[(5*p)+q]
return result_key
### 수정된 메세지의 글자쌍에 대해 키를 이용하여 암호화하는 메소드defgetResultMsg(pairs, key):# case 1) 암호판의 같은 행에 존재하는 쌍이면 우측 한 칸씩 밀어서# case 2) 같은 행에 존재하지 않고 같은 열에 존재하면 아래로 한 칸씩 밀어서# case 3) 서로 다른 행/열에 존재하는 경우 서로의 열값을 바꾼 위치로
pair_arr = []
for i inrange(0,len(pairs)-1,2):
pair_arr.append(pairs[i]+pairs[i+1])
result = ''for pair in pair_arr:
result += getModifiedKey(pair, key)
print(result)
defgetModifiedKey(pair, key):
location = [
[-1, -1], # 첫번째 글자의 위치
[-1, -1] # 두번째 글자의 위치
]
for p inrange(0,5):
for q inrange(0,5):
if pair[0] == key[p][q]:
location[0][0] = p
location[0][1] = q
if pair[1] == key[p][q]:
location[1][0] = p
location[1][1] = q
if location[0][0] == location[1][0]:
# case 1) 암호판의 같은 행에 존재하는 쌍이면 우측 한 칸씩 밀어서
location[0][1] = (location[0][1] + 1)%5
location[1][1] = (location[1][1] + 1)%5elif location[0][1] == location[1][1]:
# case 2) 같은 행에 존재하지 않고 같은 열에 존재하면 아래로 한 칸씩 밀어서
location[0][0] = (location[0][0] + 1)%5
location[1][0] = (location[1][0] + 1)%5else:
# case 3) 서로 다른 행/열에 존재하는 경우 서로의 열값을 바꾼 위치로
temp = location[0][1]
location[0][1] = location[1][1]
location[1][1] = temp
return (key[location[0][0]][location[0][1]] + key[location[1][0]][location[1][1]])
# 1. 메세지/키 입력받기
msg_input = input()
key_input = input()
# 2. 2글자 쌍으로 나누기
pairs = getPair(msg_input)
# 3. 입력받은 키를 5*5의 형태로 변경
key = getKey(key_input)
# 4. 쌍마다 암호화
getResultMsg(pairs, key)
파이썬을 사용하면 itertools 내 permutations 메소드를 써서 바로 풀이가 가능하지만 스위프트는 그런거 없음 왜..왜...
처음에는 1부터 n까지의 정수가 담긴 배열을 돌면서 하나씩 추가하고 배열에서 삭제해나가는 로직으로 생각했는데, 이러면 m중 반복문을 돌아야함 (그래도 시간복잡도가 O(N^m)이라 시간초과는 안 나겠지만 구현하기 까다로울 것 같아서 일단 포기)
1이상 n이하 정수 중에서 m개를 뽑는 방법은 DFS/BFS를 사용할 수 있는데
n이 4이고, m이 2인 경우를 생각해보면 1부터 4사이의 정수 중에 2개를 선택해야함
선택된 수를 담을 배열은 아래와 같은 경우의 수들을 가질 수 있음
[ ] -> [1] -> [1,2]
[ ] -> [1] -> [1,3]
[ ] -> [1] -> [1,4]
[ ] -> [2] -> [1,2]
[ ] -> [2] -> [2,3]
[ ] -> [2] -> [2,4]
...
[ ] -> [4] -> [3,4]
위 경우들은 트리로 시각화 할 수 있고, 각 노드들을 탐색하면서 노드를 구성하는 정수배열의 크기가 m인 경우만 중복없이 출력시키면 됨
는 그나마 익숙한 BFS로 구현했더니 시간초과
/// 시간초과난 코드import Foundation
funcsolution(_n: Int, _m: Int) -> Void {
var results: [[Int]] = []
for i in1...n { results.append([i]) }
// 수열 생성for_in0..<m {
for arr in results {
var temp: [[Int]] = []
for i in1...n {
if arr.contains(i) { continue }
var temp_arr = arr
temp_arr.append(i)
temp.append(temp_arr)
}
for t in temp {
if!results.contains(t) { results.append(t) }
}
}
}
// 사전 순으로 정렬var sorted_results: [[Int]] = []
for arr in results { if (arr.count == m) { sorted_results.append(arr) } }
sorted_results = sorted_results.sorted(by: { $0[0] <$1[0] })
// 정답 출력for arr in sorted_results {
var str =""for a in arr { str +="\(a) " }
print(str)
}
}
let input =readLine()!.components(separatedBy: " ")
solution(Int(input[0])!, Int(input[1])!)
구글링했더니 대부분 백트래킹으로 풀었음
백트래킹은 DFS와 비슷하지만 DFS는 종료 조건만 가지고 무지성 재귀함수를 사용하고, 백트래킹은 답이 있을 것 같은 경우에만 탐색하는 것이 차이점임
백트래킹에서 쓰이는 '유망함', '유망하지않음', '가지치기'의 용어도 정답 존재 가능성과 연관된 것임
- 유망함 : 정답을 찾을 수 있는 가능성 O
- 유망하지않음 : 정답을 찾을 가능성 X
- 가지치기 : 유망하지 않은 경우를 제외하는 것
(아무튼 다시 이 문제로 돌아와서) BFS 풀이는 배열의 수가 0개 -> 1개 -> 2개 -> ... -> m개인 순서로 노드들을 탐색하기 때문에, 배열의 길이가 0개부터 m-1개인 탐색할 필요가 없는 경우까지 고려하게 됨
그리고 모든 결과 배열을 다 포함하고 마지막에 탐색하면서 길이가 m인 배열을 사전순으로 출력하기 위해 따로 정렬도 해줘야 함
근데 백트래킹 풀이는 가장 적은 숫자부터 구성된 배열 중, 길이가 m인 경우에만 출력하게 하면 되니까 불필요한 경우의 고려와 정렬 코드가 삭제될 수 있음
그럼 백트래킹을 쓰려면 뭐가 유망한 거고, 뭐가 유망하지 않은 건지를 알아야 하는데 n = 4, m = 2인 경우를 예시로 보면,
결과배열이 [1]인 경우에는 1부터 4까지 중 1을 제외하고 추가해야함
이런 생각들로 아래처럼 구현하고 제출했더니 성공,,
코드구현 (스위프트사용)
import Foundation
funcsolution(_n: Int, _m: Int) -> Void {
let temp:[Int] = []
dfs(arr: temp, m: m, n: n)
}
funcdfs(arr: [Int], m: Int, n: Int) -> Void {
if (arr.count == m) {
var str =""for a in arr { str +="\(a) " }
print(str)
return
}
var temp = arr
for p in1...n {
if!temp.contains(p) {
temp.append(p) // 1부터 n 사이의 배열에 없는 숫자 중 젤 작은 거 추가
dfs(arr: temp, m: m, n: n) // 위에서 숫자 새로 추가한 배열로 다시 검사
temp.remove(at: temp.count-1) // 위에서 검사 끝나고 오면 가장 최근에 추가했던거 삭제(그 자리에 다른 새로운거 넣어보려고)
}
}
}
let input =readLine()!.components(separatedBy: " ")
solution(Int(input[0])!, Int(input[1])!)
DFS/BFS로 풀 수 있을 것 같아도 시간 복잡도 한 번 더 고려해보고, 뭔가 될 것 같아서 풀었는데 시간초과나면 백트래킹 풀이도 고려해보자