#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 10
#define INF 987654321

int list[MAXN][MAXN];
int ret = INF;
int cnt;
int type[5] = { 5, 5, 5, 5, 5 };

void dfs(int y, int x) {
	if (x == MAXN) {
		dfs(y + 1, 0);
		return;
	}
	if (y == MAXN) {
		//다 확인했으면 최소 값 확인
		ret = min(ret, cnt);
		return;
	}
	if (list[y][x] == 0) {
		dfs(y, x + 1);
		return;
	}
	for (int len = 4; len >= 0; len--) {
		if (type[len] == 0 || y + len >= MAXN || x + len >= MAXN) continue;

		bool is_zero = false;
		for (int i = 0; i <= len; i++) {
			for (int j = 0; j <= len; j++) {
				if (list[i + y][j + x] == 0) {
					is_zero = true;
					break;
				}
			}
			if (is_zero) break;
		}
		if (is_zero) continue;

		for (int i = 0; i <= len; i++) {
			for (int j = 0; j <=len; j++) {
				list[i + y][j + x] = 0;
			}
		}

		cnt++;
		type[len]--;

		dfs(y, x + len);

		for (int i = 0; i <= len; i++) {
			for (int j = 0; j <= len; j++) {
				list[i + y][j + x] = 1;
			}
		}

		cnt--;
		type[len]++;

	}
}

int main() {

	for (int i = 0; i < 10; i++) {
		for (int j = 0; j < 10; j++) {
			scanf("%d", &list[i][j]);
		}
	}

	dfs(0, 0);
	if (ret == INF) {
		printf("%d\n", -1);
	}
	else {
		printf("%d\n", ret);
	}

	

	return 0;
}

 

1. 첫 번째는 그리디로 가장 큰 종이부터 붙였지만 작은 종이를 먼저 붙이는 경우가 존재해서 불가능해서 브루트 포스로 다시 생각.

 

2. 5개 종이를 채우는 순서를 나열하면 5!가지이므로 그 순열로 dfs 돌렸으나 실패 -> 종이를 앞에서 부터 순서대로 채우지 않는 경우에서 반례 발생

 

3. dfs 다시 설계. 첫 줄부터 1~5번 종이를 모두 시도해보면서 dfs로 완전탐색을 시도한다. -> 올바른 dfs이므로 성공

 

** dfs, bfs 설계 방식이 자꾸 순열, 조합 방식으로 접근하게된다. 올바른 완전 탐색 설계를 할 수 있도록 조심할 것.

+ Recent posts