문제출처 : https://www.acmicpc.net/problem/14889


1. 문제요약

- 총 N명의 사람을 N/2 명씩 팀을 나눔

- 사람 번호를 1, 2, 3, 4라 했을때, 팀 1은 1, 2 / 팀 2는 3, 4

- 팀 능력치는 s[1][2] + s[2][1] 

                  s[3][4] + s[4][2] 이다.(s[1][2], s[2][1]은 서로 다를 수 있다.)

- 팀 능력치 차이가 최소값은?


- 4 <= N <= 20 (N은 짝수)


2. 접근방법

- 한명의 사람이 스타트팀인지 링크 팀인지 구분

- 2^N


3. 시간복잡도

- 2^N


4. 회고

- 난 팀 능력치 계산을 팀을 만들 때 마다 하게 했는데...(사실 재귀를 거치면서 합산하면 된다고 생각은 했지만, 구현을 못했음)

- 그냥 for문으로 선택된 팀원이 i 이미 팀은 팀원을 1, 2 라 하면 sum += s[i][j] + s[j][i]; 하면 되는데...


- 스타트팀 : 1, 2 / 링크팀 : 3, 4 인 경우와

  스타트팀 : 3, 4 / 링크팀 : 1, 2 인 경우는 팀 능력치 차이가 같다.


- 난 이걸 해결 못해서 그냥 모든 경우(2^N)으로 해결했다.


- 해결하는 가장 쉬운 방법은 그냥 1을 한팀에 고정시키면 된다.


- next_permutation으로 4명이면 0 0 1 1을 순열로 만들어서 0 인경우 A팀 1 인경우 B팀으로 구분시키는 방법도 있음

- 사람을 순열돌리는 것보다 시간이 빠르며 최악 20! / 10! * 10! = 190,000



소스코드



[출처 : BOJ, 문제에 대한 모든 권리는 BOJ(acmicpc.net, startlink)에 있음]

'먹고살려면 > boj' 카테고리의 다른 글

BOJ 14503 로봇 청소기  (0) 2018.02.12
BOJ 14888 연산자 끼워넣기  (0) 2018.02.12
BOJ 2146 다리 만들기  (0) 2018.02.11
BOJ 2178 미로 탐색  (0) 2018.02.11
BOJ 7576 토마토  (0) 2018.02.08

문제출처 : https://www.acmicpc.net/problem/2146


1. 문제요약

- 상하좌우로 연결된 섬이 여러개 있음

- 두 섬을 연결하는 최소 다리 길이는?

- 다리의 연결도 상하좌우

- 1 <= n <= 100

- 0은 바다 1은 육지


2. 접근방법

- dfs로 섬마다 번호를 붙임

- bfs로 섬을 한칸씩 확장해나가면서 다른섬을 만나면 다리길이를 비교하여 최소인 경우를 저장


3. 시간복잡도

- O(2n^2)


4. 회고

- queue를 쓰면서 생각지도 못한 경우가 발생함.......

- queue에 들어간 순서에 따라서 답이 달라질 수 있음

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

int n, map[101][101], dist[101][101];
int dr[4] = { -1, 0, 1, 0 };
int dc[4] = { 0, -1, 0, 1 };
queue<pair<int, int> > q;

void dfs(int r, int c, int cnt){
	dist[r][c] = 1;
	map[r][c] = cnt;
	q.push(make_pair(r, c));

	for (int k = 0; k < 4; k++){
		int nr = r + dr[k];
		int nc = c + dc[k];

		if (0 <= nr && nr < n && 0 <= nc && nc < n && dist[nr][nc] == 0 && map[nr][nc] == 1){
			dfs(nr, nc, cnt);
		}
	}
}

int main(void){
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> map[i][j];

	int cnt = 1;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			if (dist[i][j] == 0 && map[i][j] == 1)
				dfs(i, j, cnt++);

	bool isans = false;
	while (!q.empty() && !isans){
		int r = q.front().first;
		int c = q.front().second;
		q.pop();

		for (int k = 0; k < 4; k++){
			int nr = r + dr[k];
			int nc = c + dc[k];

			if (0 <= nr && nr < n && 0 <= nc && nc < n){
				if (map[nr][nc] == 0){
					q.push(make_pair(nr, nc));
					map[nr][nc] = map[r][c];
					dist[nr][nc] = dist[r][c] + 1;
				}
                                // 가장 먼저 다른 섬을 발견하면 무조건 최소 다리 길이를 만족 할줄 알았는데 queue에 들어간 순서에 따라 답이 달라 질 수 있음. 반례는 아래 참조
				else if (map[nr][nc] != map[r][c]){
					cout << dist[r][c] + dist[nr][nc] - 2 << "\n";
					isans = true;
					break;
				}
			}
		}
	}

	return 0;
}

- 반례(답 2)

5

10001

00000

00000

00000

11001

인 경우 첫번째 행 좌우섬이 큐에 먼저 들어가기 때문에 아래 다리 2가 아닌 3이 출력됨



소스코드



[출처 : BOJ, 문제에 대한 모든 권리는 BOJ(acmicpc.net, startlink)에 있음]

'먹고살려면 > boj' 카테고리의 다른 글

BOJ 14888 연산자 끼워넣기  (0) 2018.02.12
BOJ 14889 스타트와 링크  (0) 2018.02.12
BOJ 2178 미로 탐색  (0) 2018.02.11
BOJ 7576 토마토  (0) 2018.02.08
BOJ 4963 섬의 개수  (0) 2018.02.08

문제출처 : https://www.acmicpc.net/problem/2178


1. 문제요약

- n * m 크기의 맵이 주어짐

- 1은 갈 수 있는 곳, 0은 갈 수 없는 곳

- (1, 1) 에서 출발해서 (n, m) 까지 지나는 최소 칸수는?

- (1, 1), (n, m) 도 칸 횟수에 포함

- 2 <= n, m <= 100


2. 접근방법

- 맵 최소 이동횟수 = bfs


3. 시간복잡도

- O(n*m)


4. 회고



소스코드



[출처 : BOJ, 문제에 대한 모든 권리는 BOJ(acmicpc.net, startlink)에 있음]

'먹고살려면 > boj' 카테고리의 다른 글

BOJ 14889 스타트와 링크  (0) 2018.02.12
BOJ 2146 다리 만들기  (0) 2018.02.11
BOJ 7576 토마토  (0) 2018.02.08
BOJ 4963 섬의 개수  (0) 2018.02.08
BOJ 14890 경사로  (0) 2018.02.07

+ Recent posts