μ½”λ”©ν…ŒμŠ€νŠΈ/BOJ

[λ°±μ€€ 14889] μŠ€νƒ€νŠΈμ™€ 링크 (C++)

kite707 2022. 1. 5.

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

 

14889번: μŠ€νƒ€νŠΈμ™€ 링크

예제 2의 κ²½μš°μ— (1, 3, 6), (2, 4, 5)둜 νŒ€μ„ λ‚˜λˆ„λ©΄ 되고, 예제 3의 κ²½μš°μ—λŠ” (1, 2, 4, 5), (3, 6, 7, 8)둜 νŒ€μ„ λ‚˜λˆ„λ©΄ λœλ‹€.

www.acmicpc.net

아이디어

λ‚˜λŠ” 문제λ₯Ό 3가지 파트둜 λ‚˜λˆ μ„œ ν’€μ—ˆλ‹€.

1. μž…λ ₯을 λ°›λŠ” λΆ€λΆ„

2. νŒ€μ„ μ§œλŠ” λΆ€λΆ„

3. μ§œμ—¬μ§„ νŒ€μ„ μ΄μš©ν•΄μ„œ 점수λ₯Ό κ³„μ‚°ν•˜κ³  큐에 기둝

 

μž…λ ₯을 λ°›κ³ , μ§œμ—¬μ§„ νŒ€μ„ μ΄μš©ν•΄ 점수λ₯Ό κ³„μ‚°ν•˜λŠ” 것을 어렡지 μ•Šλ‹€. 이 문제의 핡심적인 뢀뢄은 νŒ€μ„ μ§œλŠ” 뢀뢄이닀. κ·Έ 뢀뢄은 μ•„λž˜μ™€ 같이 κ΅¬ν˜„ν•˜μ˜€λ‹€. 

이 문제의 κ²½μš°μ—λŠ” μ‚¬λžŒμ΄ μŠ€νƒ€νŠΈνŒ€ ν˜Ήμ€ λ§ν¬νŒ€μ΄κΈ° λ•Œλ¬Έμ— μŠ€νƒ€νŠΈνŒ€μ— μ ˆλ°˜μ„ λ°°μ •ν•˜λ©΄ λ‚˜λ¨Έμ§€λŠ” μžλ™μœΌλ‘œ λ§ν¬νŒ€μ΄ λœλ‹€. 

//νŒ€μ„ μ§œλŠ” ν•¨μˆ˜
//curteamsiz : ν˜„μž¬ νŒ€μ— λͺ‡ λͺ…이 λ“€μ–΄μ™”λŠ”κ°€
//before_end : λͺ‡ 번 μ‚¬λžŒκΉŒμ§€ νŒ€μ— 배치λ₯Ό ν–ˆλŠ”κ°€
void maketeam(int curteamsiz, int before_end) {
    //νŒ€ 인원이 λͺ¨λ‘ μ°° 경우(전체 μΈμ›μ˜ 절반이 μŠ€νƒ€νŠΈνŒ€μœΌλ‘œ 배치 μ™„λ£Œ)
	if (curteamsiz == n/2) {
        //νŒ€ λ°°μΉ˜κ°€ μ™„λ£ŒλμœΌλ‹ˆ μŠ€νƒ€νŠΈνŒ€μ˜ 점수-링크 νŒ€μ˜ 점수
		int save = calculate_start()-calculate_link();
		if (save < 0) {
            //값이 음수이면 μ–‘μˆ˜λ‘œ λ°”κΏ”μ€€λ‹€.
			save *= -1;
		}
        //μš°μ„ μˆœμœ„ 큐에 μ‚½μž…ν•œλ‹€.
		q.push(save);
	}
	else {
		for (int i = before_end+1; i <= n; i++) {
            //i번 μ‚¬λžŒμ„ μŠ€νƒ€νŠΈνŒ€μœΌλ‘œ 배치
			people[i] = 1;
            //이후 i+1번 μ‚¬λžŒλΆ€ν„° νŒ€ 배치 μ‹œμž‘
			maketeam(curteamsiz + 1, i);
            //μˆ˜ν–‰ 이후 i번 μ‚¬λžŒμ„ λ‹€μ‹œ λ§ν¬νŒ€μœΌλ‘œ 배치
			people[i] = 0;
		}
	}
	
}

 

전체 μ½”λ“œ

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

int arr[21][21];
int n, s;
//μŠ€νƒ€νŠΈνŒ€μ€ 1, λ§ν¬νŒ€μ€ 0
int people[21];

priority_queue <int, vector<int>, greater<int>> q;

//μŠ€νƒ€νŠΈ νŒ€μ˜ 점수 계산 ν•¨μˆ˜
int calculate_start() {
	int startscore = 0;
	vector<int> teamstart;
	for (int i = 1; i <= n; i++) {
		if (people[i] == 1) {
			teamstart.push_back(i);
		}
	}

	for (int i = 0; i < teamstart.size() - 1; i++) {
		for (int j = i + 1; j < teamstart.size(); j++) {
			startscore += arr[teamstart[i]][teamstart[j]] + arr[teamstart[j]][teamstart[i]];
		}
	}
	return startscore;
}

//링크 νŒ€μ˜ 점수 κ³„μ‚°ν•¨μˆ˜
int calculate_link() {
	int linkscore = 0;
	vector<int> teamlink;
	for (int i = 1; i <= n; i++) {
		if (people[i] == 0) {
			teamlink.push_back(i);
		}
	}

	for (int i = 0; i < teamlink.size() - 1; i++) {
		for (int j = i + 1; j < teamlink.size(); j++) {
			linkscore += arr[teamlink[i]][teamlink[j]] + arr[teamlink[j]][teamlink[i]];
		}
	}
	return linkscore;
}


//νŒ€μ„ μ§œλŠ” ν•¨μˆ˜
//curteamsiz : ν˜„μž¬ νŒ€μ— λͺ‡ λͺ…이 λ“€μ–΄μ™”λŠ”κ°€
//before_end : λͺ‡ 번 μ‚¬λžŒκΉŒμ§€ νŒ€μ— 배치λ₯Ό ν–ˆλŠ”κ°€
void maketeam(int curteamsiz, int before_end) {
	//νŒ€ 인원이 λͺ¨λ‘ μ°° 경우(전체 μΈμ›μ˜ 절반이 μŠ€νƒ€νŠΈνŒ€μœΌλ‘œ 배치 μ™„λ£Œ)
	if (curteamsiz == n / 2) {
		//νŒ€ λ°°μΉ˜κ°€ μ™„λ£ŒλμœΌλ‹ˆ μŠ€νƒ€νŠΈνŒ€μ˜ 점수-링크 νŒ€μ˜ 점수
		int save = calculate_start() - calculate_link();
		if (save < 0) {
			//값이 음수이면 μ–‘μˆ˜λ‘œ λ°”κΏ”μ€€λ‹€.
			save *= -1;
		}
		//μš°μ„ μˆœμœ„ 큐에 μ‚½μž…ν•œλ‹€.
		q.push(save);
	}
	else {
		for (int i = before_end + 1; i <= n; i++) {
			//i번 μ‚¬λžŒμ„ μŠ€νƒ€νŠΈνŒ€μœΌλ‘œ 배치
			people[i] = 1;
			//이후 i+1번 μ‚¬λžŒλΆ€ν„° νŒ€ 배치 μ‹œμž‘
			maketeam(curteamsiz + 1, i);
			//μˆ˜ν–‰ 이후 i번 μ‚¬λžŒμ„ λ‹€μ‹œ λ§ν¬νŒ€μœΌλ‘œ 배치
			people[i] = 0;
		}
	}

}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> arr[i][j];
		}
	}
	maketeam(0, 1);
	cout << q.top();

}

 

λŒ“κΈ€