Hello Ocean! 🌼

[λ°±μ€€/C++] 1941. μ†Œλ¬Έλ‚œ 칠곡주 λ³Έλ¬Έ

Algorithm

[λ°±μ€€/C++] 1941. μ†Œλ¬Έλ‚œ 칠곡주

bba_dda 2021. 8. 24. 19:03
λ°˜μ‘ν˜•

문제

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

 

1941번: μ†Œλ¬Έλ‚œ 칠곡주

총 25λͺ…μ˜ μ—¬ν•™μƒλ“€λ‘œ 이루어진 μ—¬ν•™μƒλ°˜μ€ 5*5의 μ •μ‚¬κ°ν˜• 격자 ν˜•νƒœλ‘œ μžλ¦¬κ°€ λ°°μΉ˜λ˜μ—ˆκ³ , μ–Όλ§ˆ μ§€λ‚˜μ§€ μ•Šμ•„ μ΄λ‹€μ†œκ³Ό μž„λ„μ—°μ΄λΌλŠ” 두 학생이 두각을 λ‚˜νƒ€λ‚΄λ©° λ‹€λ₯Έ 학생듀을 νœ˜μ–΄μž‘κΈ° μ‹œμž‘

www.acmicpc.net

총 25λͺ…μ˜ μ—¬ν•™μƒλ“€λ‘œ 이루어진 μ—¬ν•™μƒλ°˜μ€ 5*5의 μ •μ‚¬κ°ν˜• 격자 ν˜•νƒœλ‘œ μžλ¦¬κ°€ λ°°μΉ˜λ˜μ—ˆκ³ , μ–Όλ§ˆ μ§€λ‚˜μ§€ μ•Šμ•„ μ΄λ‹€μ†œκ³Ό μž„λ„μ—°μ΄λΌλŠ” 두 학생이 두각을 λ‚˜νƒ€λ‚΄λ©° λ‹€λ₯Έ 학생듀을 νœ˜μ–΄μž‘κΈ° μ‹œμž‘ν–ˆλ‹€. 곧 λͺ¨λ“  여학생이 ‘μ΄λ‹€μ†œνŒŒ’와 ‘μž„λ„μ—°νŒŒ’의 두 파둜 κ°ˆλΌμ§€κ²Œ λ˜μ—ˆμœΌλ©°, μ–Όλ§ˆ μ§€λ‚˜μ§€ μ•Šμ•„ ‘μž„λ„μ—°νŒŒ’κ°€ μ„Έλ ₯을 ν™•μž₯μ‹œν‚€λ©° ‘μ΄λ‹€μ†œνŒŒ’λ₯Ό μœ„ν˜‘ν•˜κΈ° μ‹œμž‘ν–ˆλ‹€.

μœ„κΈ°μ˜μ‹μ„ λŠλ‚€ ‘μ΄λ‹€μ†œνŒŒ’의 학생듀은 과감히 ν˜„μž¬μ˜ 체제λ₯Ό ν¬κΈ°ν•˜κ³ , ‘μ†Œλ¬Έλ‚œ 칠곡주’λ₯Ό κ²°μ„±ν•˜λŠ” 것이 μœ μΌν•œ 생쑴 μˆ˜λ‹¨μž„μ„ κΉ¨λ‹¬μ•˜λ‹€. ‘μ†Œλ¬Έλ‚œ 칠곡주’λŠ” λ‹€μŒκ³Ό 같은 κ·œμΉ™μ„ λ§Œμ‘±ν•΄μ•Ό ν•œλ‹€.

  1. 이름이 이름인 만큼, 7λͺ…μ˜ μ—¬ν•™μƒλ“€λ‘œ κ΅¬μ„±λ˜μ–΄μ•Ό ν•œλ‹€.
  2. κ°•ν•œ 결속λ ₯을 μœ„ν•΄, 7λͺ…μ˜ μžλ¦¬λŠ” μ„œλ‘œ κ°€λ‘œλ‚˜ μ„Έλ‘œλ‘œ λ°˜λ“œμ‹œ 인접해 μžˆμ–΄μ•Ό ν•œλ‹€.
  3. ν™”ν•©κ³Ό λ²ˆμ˜μ„ μœ„ν•΄, λ°˜λ“œμ‹œ ‘μ΄λ‹€μ†œνŒŒ’의 ν•™μƒλ“€λ‘œλ§Œ ꡬ성될 ν•„μš”λŠ” μ—†λ‹€.
  4. κ·ΈλŸ¬λ‚˜ 생쑴을 μœ„ν•΄, ‘μ΄λ‹€μ†œνŒŒ’κ°€ λ°˜λ“œμ‹œ μš°μœ„λ₯Ό 점해야 ν•œλ‹€. λ”°λΌμ„œ 7λͺ…μ˜ 학생 쀑 ‘μ΄λ‹€μ†œνŒŒ’의 학생이 적어도 4λͺ… 이상은 λ°˜λ“œμ‹œ ν¬ν•¨λ˜μ–΄ μžˆμ–΄μ•Ό ν•œλ‹€.

μ—¬ν•™μƒλ°˜μ˜ 자리 λ°°μΉ˜λ„κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, ‘μ†Œλ¬Έλ‚œ 칠곡주’λ₯Ό κ²°μ„±ν•  수 μžˆλŠ” λͺ¨λ“  경우의 수λ₯Ό κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

 

풀이

[κ²°λ‘ ]

25개 쀑에 7개λ₯Ό λ½‘λŠ” λͺ¨λ“  쑰합을 κ΅¬ν•΄μ„œ, ν•΄λ‹Ή 쑰합에 λŒ€ν•œ 쑰건(μ΄λ‹€μ†œνŒŒκ°€ 4λͺ… 이상인지, λͺ¨λ‘ 인접해 μžˆλŠ”μ§€)을 ν™•μΈν•΄μ„œ 쑰건에 λ§Œμ‘±ν•˜λŠ” 경우λ₯Ό μ„Έλ©΄ λœλ‹€.

 

[μ‹œλ„ 1] 

DFSλ₯Ό μ΄μš©ν•œ λ°±νŠΈλž˜ν‚Ήμ„ ν–ˆλ‹€. κ²°κ³ΌλŠ” ν‹€λ ΈμŠ΅λ‹ˆλ‹€ μ˜€λ‹€. 

λ°˜λ‘€λ₯Ό ν™•μΈν•΄λ³΄λ‹ˆ DFS의 경우 + 이런 μ‹­μž λͺ¨μ–‘μ˜ μΌ€μ΄μŠ€λŠ” μž‘μ•„λ‚Ό 수 μ—†μ—ˆλ‹€. \

 

[μ‹œλ„ 2] 

λͺ¨λ“  쑰합을 κ΅¬ν•΄μ„œ, 쑰건을 ν™•μΈν–ˆλ‹€. 

7곡주가 λͺ¨λ‘ 인접해 μžˆλŠ”μ§€ 확인할 λ•Œ, μ£Όλ¨Ήκ΅¬κ΅¬μ‹μœΌλ‘œ 7곡주 자리의 μƒν•˜μ’Œμš°μ— λ‹€λ₯Έ 7곡주가 μžˆλŠ”μ§€ ν™•μΈν–ˆλŠ”λ° 또 ν‹€λ Έλ‹€!

λ°˜λ‘€λ₯Ό ν™•μΈν•΄λ³΄λ‹ˆ 7곡주가 λͺ¨λ‘ 인접해 μžˆμ§€ μ•Šκ³  λ‘κ°œ-μ„Έκ°œ λ©μ–΄λ¦¬λ‘œ λ‚˜μ˜€λŠ” κ²½μš°κ°€ μžˆμ—ˆλ‹€.

 

[μ‹œλ„ 3 (κ²°λ‘ )]

λͺ¨λ“  쑰합을 κ΅¬ν•΄μ„œ, 쑰건을 ν™•μΈν•˜λŠ”λ° BFSλ₯Ό μ΄μš©ν–ˆλ‹€. 

μ‘°κΈˆμ΄λ‚˜λ§ˆ μ‹œκ°„λ³΅μž‘λ„λ₯Ό 쀄이기 μœ„ν•΄μ„œ, 쑰합을 λ½‘λŠ” 쀑간에 μž„λ„μ—°νŒŒ(Y)κ°€ 4λͺ… μ΄μƒμ΄λ˜λ©΄ ν•΄λ‹Ή μΌ€μ΄μŠ€λŠ” 더 이상 μ§„ν–‰ν•˜μ§€ μ•Šκ³  버렸닀. 

 

λͺ¨λ“  μ‘°ν•©μ˜ κ°―μˆ˜κ°€ 25C7 = 480,700 밖에 λ˜μ§€ μ•Šμ•„μ„œ λͺ¨λ“  쑰합을 λ‹€ 검사해도 μ‹œκ°„μ΄ˆκ³Όκ°€ λ‚˜μ§€ μ•Šμ•˜λ‹€. 

 

μ½”λ“œ

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

using namespace std;

char table[5][5];
int cache[5][5];
int answer = 0;

int dr[4] = { -1,1,0,0 };
int dc[4] = { 0,0,-1,1 };

bool isOk(vector<int> selected) {
	fill(&cache[0][0], &cache[4][5], 0);
	for (int i = 0;i < 7;i++) {
		cache[selected[i] / 5][selected[i] % 5] = 2; // 7곡주 자리 ν‘œμ‹œ
	}

	queue<pair<int, int>> q;
	q.push({ selected[0] / 5, selected[0] % 5 });
	cache[selected[0] / 5][selected[0] % 5] = 1;
	int remain = 6; 

	while (!q.empty()) {
		int r = q.front().first;
		int c = q.front().second;
		q.pop();
		for (int i = 0;i < 4;i++) {
			int newR = r + dr[i];
			int newC = c + dc[i];

			if (newR < 0 || newR>4 || newC < 0 || newC>4) continue;

			// λ°©λ¬Έν•œ 적이 μ—†λŠ” 7곡주 자리이면 
			if (cache[newR][newC] == 2) { 
				remain--;
				cache[newR][newC] = 1;
				q.push({ newR, newC });
			}
		}
	}
	// BFS탐색을 μ™„λ£Œν–ˆλŠ”λ°, 7곡주λ₯Ό λͺ¨λ‘ μ°Ύμ•˜λ‹€ -> λͺ¨λ‘ μΈμ ‘ν•΄μžˆλ‹€.
	if (remain == 0)
		return true;
	else 
		return false;
}
// 0~24 (25개) μ—μ„œ 7개 뽑기 
void combi(int start, int doyean, int count, vector<int> selected) {
	if (count == 7) {
		if (isOk(selected)) answer++;
		return;
	}
	if (table[start / 5][start % 5] == 'Y') doyean++;
	for (int i = start+1;i < 25;i++) {
		if (table[i / 5][i % 5] == 'Y') {
			// λ„μ—°νŒŒκ°€ 4λͺ… 이상이 되면 더 이상 진행x
			if (doyean + 1 > 3) continue;
		}
		selected.push_back(i);
		combi(i, doyean, count + 1, selected);
		selected.pop_back();
	}
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	for (int i = 0;i < 5;i++) {
		for (int j = 0;j < 5;j++) {
			cin >> table[i][j];
		}
	}

	for (int i = 0;i < 25;i++) 
		combi(i, 0, 1, {i});
	
	cout << answer << endl;
	return 0;
}

κ²°κ³Ό

 

λ°˜μ‘ν˜•