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

4-rivkms #13

Merged
merged 2 commits into from
Feb 25, 2024
Merged

4-rivkms #13

merged 2 commits into from
Feb 25, 2024

Conversation

rivkms
Copy link
Collaborator

@rivkms rivkms commented Feb 21, 2024

πŸ”— 문제 링크

N-queen

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

5h (μ•Œκ³ μžˆλŠ” μ½”λ“œκ°€ μ•„λ‹ˆλΌ λ‹€λ₯Έ 방법을 μƒκ°ν•˜λŠλΌ μ‹œκ°„μ΄ 더 κ±Έλ Έλ„€μš”...)
πŸ›‘ 처음 문제 λ³΄μ‹œλŠ” 뢄듀은 훨씬 였래 κ±Έλ¦¬μ‹œκΈ΄ ν• κ±°μ—μš”...!

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

▢️ λ¬Έμ œμœ ν˜•

: backtracking

βœ”οΈ 문제 μ„€λͺ…

μ²΄μŠ€νŒμ—μ„œ Queen은 μ•ž, μ˜†, λŒ€κ°μ„ μœΌλ‘œ 거리에 상관없이 움직일 수 μžˆμ–΄ 맀우 μ€‘μš”ν•œ 역할을 ν•©λ‹ˆλ‹€.
이번 λ¬Έμ œλŠ” N이 μ£Όμ–΄μ‘Œμ„ λ•Œ N*N 크기의 μ²΄μŠ€νŒμ— N개의 퀸을 μ„œλ‘œ μž‘νžˆμ§€ μ•Šλ„λ‘ λ°°μΉ˜ν•  수 μžˆλŠ” 개수λ₯Ό κ΅¬ν•˜λŠ” λ¬Έμ œμž…λ‹ˆλ‹€.

이 그림은 8 * 8 크기의 μ²΄μŠ€νŒμ—μ„œ 8개의 퀸을 λ°°μΉ˜ν•˜λŠ” 경우 쀑 ν•œ 가지λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.
μ΄λŸ¬ν•œ μ‹μœΌλ‘œ λ§Œλ“€ 수 μžˆλŠ” 경우의 수λ₯Ό μ „λΆ€ μ„Έλ©΄ λ˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

참고둜 N-Queenμ—μ„œ κ°€λŠ₯ν•œ 경우의 μˆ˜λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

‼️ DFS

이 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같이 생각할 수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.
🚩 체슀판의 ν•œ 쀄씩 μ΄λ™ν•˜λ©° 각 칸에 퀸이 λ“€μ–΄κ°ˆ 수 μžˆλŠ” λͺ¨λ“  경우λ₯Ό κ³ λ €ν•΄λ³΄μž

1. 첫 번째 쀄에 올 수 μžˆλŠ” 경우λ₯Ό λͺ¨λ‘ κ³ λ €ν•˜κ³ 
2. 1μ—μ„œ κ΅¬ν•œ κ²½μš°μ—μ„œ 두 번째 쀄에 올 수 μžˆλŠ” 경우λ₯Ό λͺ¨λ‘ κ³ λ €ν•˜κ³ 
3. 2μ—μ„œ κ΅¬ν•œ κ²½μš°μ—μ„œ μ„Έ 번째 쀄에 올 수 μžˆλŠ” 경우λ₯Ό λͺ¨λ‘ κ³ λ €ν•˜κ³ 
...

μ΄λŸ¬ν•œ 방법을 DFS(Depth-First Search)라고 ν•©λ‹ˆλ‹€.
이 λ•Œ 트리λ₯Ό μ΄μš©ν•˜κ²Œ 되면

λ‹€μŒκ³Ό 같은 μˆœμ„œμ— 따라 트리λ₯Ό νƒμƒ‰ν•˜λ©΄μ„œ μ§„ν–‰ν•˜κ²Œ 되겠죠.

πŸ›‘ 문제점

μœ„μ˜ κ·Έλ¦Όμ—μ„œ 9번이 μ•ˆλ˜λŠ” 것을 μ•„λŠ”λ°, 10번, 11λ²ˆμ„ μˆ˜ν–‰ν•΄μ•Όν• κΉŒ?
DFSλŠ” 10번과 11λ²ˆμ„ μˆ˜ν–‰ν•΄μ•Όν•¨
❓이것을 μˆ˜ν–‰ν•˜μ§€ μ•Šμ„ μˆ˜λŠ” μ—†μ„κΉŒ?

‼️ Backtracking

βœ”οΈ Backtracking : ν•΄λ₯Ό μ°ΎλŠ” 도쀑 ν•΄κ°€ μ•„λ‹ˆμ–΄μ„œ λ§‰νžˆλ©΄, λ˜λŒμ•„κ°€μ„œ λ‹€μ‹œ ν•΄λ₯Ό μ°Ύμ•„κ°€λŠ” 기법.
이 기법을 μ‚¬μš©ν•˜λ©΄ μœ„μ˜ κ·Έλ¦Όμ—μ„œ 9번이 μ•ˆλ˜λ©΄, 10~11λ²ˆμ„ μˆ˜ν–‰ν•˜μ§€ μ•Šμ•„λ„ λ©λ‹ˆλ‹€.

βœ”οΈ κ°€μ§€μΉ˜κΈ° : 더 이상 탐색할 ν•„μš”κ°€ μ—†λŠ” μƒνƒœλ₯Ό μ œμ™Έν•˜λŠ” 것
μœ„μ˜ λ‚΄μš©μ„ κ°€μ§€μΉ˜κΈ°λΌκ³  ν•˜λ©°, κ°€μ§€μΉ˜κΈ°λ₯Ό μ΄μš©ν•˜μ—¬ λΆˆν•„μš”ν•œ 연산을 μˆ˜ν–‰ν•˜μ§€ μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“ 핡심 sudo code

μœ„μ˜ λ‚΄μš©μ„ μ΄μš©ν•˜μ—¬ 핡심 μ½”λ“œλ₯Ό 짜보면

1️⃣ λ§Œμ•½ κΉŠμ΄κ°€ 체슀판의 크기에 λ„λ‹¬ν–ˆλ‹€λ©΄ 1을 λ¦¬ν„΄ν•œλ‹€. 
2️⃣ νŠΉμ • 깊이 nμ—μ„œμ˜ λͺ¨λ“  칸에 λŒ€ν•˜μ—¬ λ°˜λ³΅μ„ μˆ˜ν–‰ν•œλ‹€. 
3️⃣ ν•΄λ‹Ή μœ„μΉ˜μ— 퀸을 λ‘”λ‹€. 
4️⃣ λ§Œμ•½ n보닀 μž‘μ€ 깊이의 퀸듀에 μ˜ν•΄ ν•΄λ‹Ή 칸에 퀸을 λͺ»λ‘λŠ” 경우라면 κ°€μ§€μΉ˜κΈ°λ₯Ό μˆ˜ν–‰ν•œλ‹€. 
5️⃣ 그렇지 μ•Šλ‹€λ©΄ ν•΄λ‹Ή μ²΄μŠ€νŒμ„ μ΄μš©ν•˜μ—¬ λ‹€μŒ κΉŠμ΄μ— λŒ€ν•˜μ—¬ μž¬κ·€λ₯Ό μˆ˜ν–‰ν•˜κ³ , λ³€μˆ˜ sum에 κ·Έ 리턴값을 λ”ν•œλ‹€. 
6️⃣ 반볡이 λλ‚œ ν›„, sum을 λ¦¬ν„΄ν•œλ‹€. 

πŸ–₯️ 첫번째 접근법

♦️ μ²΄μŠ€νŒμ„ 2차원 λ°°μ—΄λ‘œ κ΅¬ν˜„ν•˜μž.

μ²΄μŠ€νŒμ„ 2차원 λ°°μ—΄λ‘œ κ΅¬ν˜„ν•˜μ—¬, Queen이 놓여진 κ²½μš°μ—λŠ” 1을, 놓을 수 μ—†λŠ” κ³³μ—μ„œλŠ” -1을 μ €μž₯ν•œλ‹€.

이λ₯Ό μ½”λ“œλ‘œ κ΅¬ν˜„ν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

▢️ κ΅¬ν˜„

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int dfs(vector<vector<int>> map, int n, int k) {
	int cnt = 0;
	vector<vector<int>> _map(n, vector<int>(n, 0));
	if (k == n) {
		return 1;
	}
	for (int i = 0; i < n; i++) {
		if (map[k][i] != -1) {
			copy(map.begin(), map.end(), _map.begin());
			for (int j = 0; j < n; j++) {
				if(j!=i)
					_map[k][j] = -1;
			}
			_map[k][i] = 1;
			for (int j = 1; j < n - k; j++) {
				_map[k + j][i] = -1;
				if (i - j >= 0) {
					_map[k + j][i - j] = -1;
				}
				if (i + j < n) {
					_map[k + j][i + j] = -1;
				}
			}		
			cnt += dfs(_map, n, k + 1);
		}
	}
	return cnt;
}

int main() {
	int n;
	cin >> n;
	int ans = dfs(vector<vector<int>>(n, vector<int>(n,0)), n, 0);
	cout << ans;
}

😭 ν•˜μ§€λ§Œ...
image
μ‹œκ°„μ΄ˆκ³Όκ°€ λœ¨λ©΄μ„œ 무언가 잘λͺ»λ˜μ—ˆμŒμ„ κΉ¨λ‹¬μ•˜λ‹€ γ… γ… 

πŸ“’ 문제점

μ•„λ§ˆ λ¬Έμ œκ°€ λ˜λŠ” 뢀뢄이 2차원 배열에 μžˆλ‹€κ³  μƒκ°ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€.
2차원 배열을 λ³΅μ‚¬ν•˜λŠ” λΆ€λΆ„, 그것을 μž¬κ·€λ‘œ λŒλ Έμ„ λ•Œ λ°œμƒν•˜λŠ” 문제라고 μƒκ°ν•˜μ—¬ μƒˆλ‘œμš΄ 방법을 κ³ μ•ˆν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

πŸ–₯️ λ‘λ²ˆμ§Έ 접근법

♦️ 2차원 λ°°μ—΄ λŒ€μ‹  1차원 배열을 μ‚¬μš©ν•΄λ³΄μž.

2차원 λ°°μ—΄μ—μ„œλŠ” κ·Έ 칸에 λ“€μ–΄μ˜¬ 수 μžˆλŠ”μ§€, μ—†λŠ”μ§€λ₯Ό μ €μž₯ν•˜μ˜€μ§€λ§Œ
1차원 λ°°μ—΄μ—μ„œλŠ” ν•΄λ‹Ή 깊이의 μ–΄λ–€ 칸으둜 λ“€μ–΄κ°€λŠ”μ§€λ₯Ό μ €μž₯ν•΄λ³΄μž

β˜‘οΈ μ˜ˆμ‹œ

μœ„ κ·Έλ¦Όμ—μ„œλŠ” {4, 1, 3, 6, 2, 7, 5, 0}이 μ €μž₯λ˜λ„λ‘ ν•΄λ΄…μ‹œλ‹€.

β–ΆοΈκ΅¬ν˜„

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int dfs(vector<int> map, int n, int k){
    int cnt = 0;
    bool check = true;
    if(n == k){
        return 1;
    }

    for(int i = 0; i<n; i++){
        map[k] = i;
        for(int j = 0; j<k; j++){
            if(map[k]==map[j] || k-j == abs(map[k]-map[j]) ){
                check = false;
                break;
            }
        }
        if(check){
            cnt+=dfs(map, n, k+1);
        }
        check = true;
    }
    return cnt;

}

int main(){
    int n, cnt = 0;
    cin >> n;

    cnt = dfs(vector<int> (n,0), n, 0);
    cout << cnt;
    return 0;
}

😁이 방법을 μ‚¬μš©ν–ˆλ”λ‹ˆ
image
μ„±κ³΅ν•˜μ˜€λ„€μš”πŸŽ–οΈ

πŸ“š μƒˆλ‘­κ²Œ μ•Œκ²Œλœ λ‚΄μš©

βœ”οΈ μœ„μ—μ„œ μ„€λͺ…ν•œ Backtrackingκ³Ό DFS에 λŒ€ν•΄ μžμ„Έν•œ κ°œλ…μ„ μ•Œμ•„λ³Ό 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

βœ”οΈ 이 λ¬Έμ œμ™€ 같이 2차원 λ°°μ—΄μ—μ„œ κ°€λŠ₯μ—¬λΆ€λ₯Ό μ €μž₯ν•  경우, 1차원 배열을 μ΄μš©ν•˜μ—¬ 더 효과적으둜 μ½”λ“œλ₯Ό 지 수 μžˆλŠ” 방법을 배울 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

βœ”οΈ λ‹€μ‹œ μ½μ–΄λ³΄λ‹ˆ PR이 κΈΈκ³  읽기 νž˜λ“€ μˆ˜λ„ μžˆκ² λ‹€κ³  생각도 λ“­λ‹ˆλ‹€. κΈ€λ‘œ ν‘œν˜„ν•˜κ³  싢은 생각이 λ§Žμ•„μ§€λ‹€λ³΄λ‹ˆ 글이 λ”λŸ¬μ›Œμ‘Œλ„€μš”... κ·Έλž˜λ„ κΈ€ λ‹€ μ½μ–΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€. πŸ˜†

Copy link
Member

@kjs254 kjs254 left a comment

Choose a reason for hiding this comment

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

κΉŠμ΄μš°μ„ νƒμƒ‰ DFSμ—μ„œ ν•„μš” μ—†λŠ” 연산을 backtrackingκ³Ό μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ μ΅œμ ν™”ν•˜λŠ” λ°©λ²•μœΌλ‘œ 잘 ν’€μ΄ν•˜μ‹  것 κ°™μŠ΅λ‹ˆλ‹€.

λ‹€λ§Œ μˆ˜λ„μ½”λ“œλ₯Ό c++둜 κ΅¬ν˜„ν•˜λŠ” 과정이 잘 μ΄ν•΄λ˜μ§€ μ•Šμ•„μ„œ λ³€μˆ˜ check에 λŒ€ν•΄ μ§ˆλ¬Έλ“œλ¦½λ‹ˆλ‹€.

Comment on lines +22 to +23
if(check){
cnt+=dfs(map, n, k+1);
Copy link
Member

Choose a reason for hiding this comment

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

μœ„ μ‘°κ±΄μ—μ„œ checkκ°€ true인 경우 μž¬κ·€λ‘œ ν•¨μˆ˜κ°€ λ°˜λ³΅λ˜λŠ”λ° checkκ°€ 정확이 λœ»ν•˜λŠ” λ°”κ°€ 어떀지 κΆκΈˆν•©λ‹ˆλ‹€.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ν•΄λ‹Ή 쑰건 μœ„μ˜ λ°˜λ³΅λ¬Έμ—μ„œ i번째 μ€„μ˜ λͺ¨λ“  칸에 퀸을 λ°°μΉ˜ν•©λ‹ˆλ‹€. 이후 ν•΄λ‹Ή 칸에 퀸을 λ†“μ•˜μ„ λ•Œ λ¬Έμ œκ°€ 생긴닀면 checkλ₯Ό false둜 μ„€μ •ν•˜κ²Œ λ©λ‹ˆλ‹€.

즉, 체슀판의 μ–΄λ–€ 칸에 퀸을 λ°°μΉ˜ν•œ ν›„ 이전에 배치된 퀸듀을 κ³ λ €ν•˜μ˜€μ„ λ•Œμ—λ„ ν•΄λ‹Ή 체슀판이 μœ νš¨ν•œμ§€ ν™•μΈν•˜λŠ” λ³€μˆ˜λΌκ³  μƒκ°ν•˜μ‹œλ©΄ 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€.

βœ”οΈ 사싀 ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ ν•΄λ‹Ή 체슀판이 μœ νš¨ν•œμ§€ ν™•μΈν•œλ‹€λ©΄ checkλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 그게 더 깔끔할 μˆ˜λ„ μžˆκ³ μš”πŸ˜

Copy link
Collaborator

@YIM2UL2ET YIM2UL2ET left a comment

Choose a reason for hiding this comment

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

λ°±νŠΈλž˜ν‚Ήμ— λŒ€ν•΄μ„œ μ‘°κΈˆμ΄λ‚˜λ§ˆ 곡뢀 ν•΄λ³Ό 수 μžˆμ—ˆκ³ , κ·Έκ±Έ μ½”λ“œλ‘œ κ΅¬ν˜„ν•˜λŠ” 아이디어 잘 μ–»μ–΄κ°‘λ‹ˆλ‹€. λ°±νŠΈλž˜ν‚Ή 곡뢀할 λ•Œκ°€ 였면 μ°Έκ³ ν•΄μ„œ 곡뢀 ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€. 제 레벨 κΈ°μ€€μœΌλ‘œ 아직은 많이 μ–΄λ ΅λ„€μš”.. μˆ˜κ³ ν•˜μ…¨μŠ΅λ‹ˆλ‹€.

Copy link
Collaborator

@mong3125 mong3125 left a comment

Choose a reason for hiding this comment

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

λ³΅μ‚¬ν•˜λŠ”κ±Έ μž¬κ·€λ‘œ λŒλ €μ„œ λ¬Έμ œκ°€ λ°œμƒν–ˆκ΅°μš”.. 일차원 λ°°μ—΄λ‘œ ν‘ΈλŠ” 방법에 λŒ€ν•΄μ„œλŠ” μ•Œκ³ μžˆμ—ˆλŠ”λ° μ΄λ²ˆμ—λ„ λ„ˆλ¬΄ μ§κ΄€μ μœΌλ‘œ μ ‘κ·Όν–ˆλ˜κ²ƒ κ°™μŠ΅λ‹ˆλ‹€. λ‹€μ‹œ λ˜μƒˆκΈ°κ³  κ°‘λ‹ˆλ‹€.

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.

4 participants