CS/Algorithm

[SWEA][C++] 2112 보호필름

별토끼. 2020. 2. 17. 20:12
반응형
문제

SW Expert Academy 모의 문제 2112 보호필름

풀이

열마다 k개 연속으로 A 혹은 B 보호필름이 있으면 합격입니다. 모든 열이 이 조건에 만족하려면, 최소 몇 개의 행에 투약을 해야하는지가 문제입니다. 

1. 투약 횟수를 지정해 줍니다.

2. 투약 횟수만큼 조합을 해줍니다. DFS를 이용했습니다.

3. 모든 열이 합격 기준에 만족하는지 확인합니다.

처음 구현했을 때 시간 초과가 나서 벡터를 배열로 바꾸고, 하나의 열이라도 합격 기준에 미치지 못하면 바로 빠져나오도록 최대한 가지치기했습니다. 시간 관리에 유의하면서 풀어야 하는 문제입니다.

코드
#include <iostream>
using namespace std;
int answer = 987654321;
int map[14][22];
int d, w, k;
bool isFin = false;
int list[14];
void dfs(int cnt, int valu, int res) {
	
	if (valu == res) {
		if (isFin) return;
		int val = 0;
		//연속확인
		for (int i = 1; i <= w; i++) {
			bool isOK = false;
			int start = 1;
			int tmp = 1;
			for (int j = 2; j <= d; j++) {
				if (map[j][i] == map[start][i]) {
					tmp++;
				}
				else {
					start = j;
					tmp = 1;
				}
				if (k == tmp) {
					isOK = true;
					val++;
					break;
				}
			}
			if (!isOK) break;
		}
		if (val == w) {
			cout << cnt << endl;
			isFin = true;
		}
		return;
	}
	if (cnt > d ) return;
	//투약할 위치 지정

	dfs(cnt + 1, valu, res);
	int color[21];
	for (int i = 1; i <= w; i++) {
		color[i] = map[cnt][i];
	}

	for (int i = 1; i <= w; i++) {
		map[cnt][i] = 0;
	}
	dfs(cnt + 1, valu + 1, res);

	for (int i = 1; i <= w; i++) {
		map[cnt][i] = 1;
	}
	dfs(cnt + 1, valu + 1, res);

	for (int i = 1; i <= w; i++) {
		map[cnt][i] = color[i];
	}
}
int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
	int T;
	cin >> T;
	for (int t = 1; t <= T; t++) {
		answer = 987654321;
		isFin = false;
		cin >> d >> w >> k;
		for (int i = 1; i <= d; i++) {
			for (int j = 1; j <= w; j++) {
				cin >> map[i][j];
			}
		}
		for (int r = 0; r < d; r++) {
			dfs(1, 0, r);

			if (isFin) {
				answer = r;
				break;
			}
		}
		cout << "#" << t << " " << answer << endl;
	}
}
반응형