# 본인 풀이
#include<bits/stdc++.h>
using namespace std;
int n;
int a[10][10];
int visited[10][10];
int dy[4] = {-1, 0, 1, 0};
int dx[4] = {0, 1, 0, -1};
int dfs(int y, int x, int check){
int ret = 1;
visited[y][x] = 1;
for (int i = 0; i < 4; i++){
int ny = y + dy[i];
int nx = x + dx[i];
if(ny < 0 || nx < 0 || ny >= n || nx >= n){
continue;
}
// b는 0 또는 1, 0에 해당하는 넓이와 1에 해당하는 넓이를 알기 위함
// 0인곳만 방문
if(a[ny][nx] == check && !visited[ny][nx]){
ret += dfs(ny, nx, check);
}
}
return ret;
}
string compress(int sx,int sy, int n){
string str = "";
memset(visited, 0, sizeof(visited));
if (n == 1)
{
return to_string(a[sy][sx]);
}
for (int i = sy; i < sy + n; i++)
{
for (int j = sx; j < sx + n; j++)
{
if (visited[i][j])
{
continue;
}
int area0 = dfs(i, j, 0);
int area1 = dfs(i, j, 1);
// DFS 한번으로 전체 넓이가 n*n이 되지 않으면 컴프레싱
if(area0 != n * n && area1 != 1){
str += "(";
string lefttop = compress(sx, sy, n / 2);
string righttop = compress(sx + n/2, sy, n/2);
string leftbottom = compress(sx, sy + n/2, n/2);
string rightbottom = compress(sx + n/2,sy + n/2, n/2);
if(lefttop == righttop && righttop == leftbottom && leftbottom == rightbottom){
str = lefttop;
return str;
} else {
str += lefttop;
str += righttop;
str += leftbottom;
str += rightbottom;
}
str += ")";
return str;
}
if (area0 == 1){
return "1";
}else{
return "0";
}
}
}
return str;
}
// 컴프레싱은 잘 됐는데 괄호삽입이 안됨 - 괄호삽입 기준점 찾기
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n;
for (int i = 0; i < n; i++){
string s;
cin >> s;
for (int j = 0; j < n; j++){
a[i][j] = s[j] - '0';
}
}
// 1. DFS 각 area값이 2의 제곱수 -> 컴프레스
// 2. DFS 각 area값이 2의 제곱이 아님 -> 2로 나누기
string ret;
ret = compress(0, 0, n);
cout << ret << "\n";
return 0;
}
- 풀다가 너무 지저분해져서 포기
- 반례 짜맞추기식으로 풀이하게되었음 (괄호삽입 실패 및 1001 입력 반례 실패)
- 시작점과 사이즈가 달라지도록 분할정복 재귀는 구현했음
# 모범 답안
#include<bits/stdc++.h>
using namespace std;
int n;
string s;
char a[101][101];
string quad(int y, int x, int size){
if(size == 1){
return string(1, a[y][x]);
}
char b = a[y][x];
string ret = "";
for (int i = y; i < y + size; i++){
for (int j = x; j < x + size; j++){
// 문자 하나만 달라도 오염된 사각형이다
if(b!=a[i][j]){
ret += "(";
ret += quad(y, x, size / 2);
ret += quad(y, x + size / 2 , size / 2);
ret += quad(y + size / 2, x, size / 2);
ret += quad(y + size / 2, x + size / 2, size / 2);
ret += ")";
return ret;
}
}
}
return string(1, a[y][x]);
}
// 컴프레싱은 잘 됐는데 괄호삽입이 안됨 - 괄호삽입 기준점 찾기
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n;
for (int i = 0; i < n; i++){
cin >> s;
for (int j = 0; j < n; j++){
a[i][j] = s[j];
}
}
cout << quad(0, 0, n) << "\n";
return 0;
}
# 복습(7/17)
실패
#include<bits/stdc++.h>
using namespace std;
int n;
int quad[64][64];
string solution(int y, int x, int len){
string ret = "(";
if (len == 1){
return to_string(quad[y][x]);
}
bool flag = 0;
int prev = quad[y][x];
for (int i = y; i < y + len / 2; i++){
for (int j = x; j < x + len / 2; j++){
if(quad[i][j] != prev){
flag = 1;
break;
}
}
if(flag){
break;
}
}
if(flag){
ret += solution(y, x, len / 2);
}else{
ret += to_string(prev);
}
flag = 0;
prev = quad[y][x + len / 2];
for (int i = y; i < y + len / 2; i++){
for (int j = x + len / 2; j < x + len; j++){
if(quad[i][j] != prev){
flag = 1;
break;
}
}
if(flag){
break;
}
}
if(flag){
ret += solution(y, x + len / 2, len / 2);
}else{
ret += to_string(prev);
}
flag = 0;
prev = quad[y + len / 2][x];
for (int i = y + len / 2; i < y + len ; i++){
for (int j = x; j < x + len / 2; j++){
if(quad[i][j] != prev){
flag = 1;
break;
}
}
if(flag){
break;
}
}
if(flag){
ret += solution(y + len / 2, x, len / 2);
}else{
ret += to_string(prev);
}
flag = 0;
prev = quad[y + len / 2][x + len / 2];
for (int i = y + len / 2; i < y + len ; i++){
for (int j = x + len / 2; j < x + len; j++){
if(quad[i][j] != prev){
flag = 1;
break;
}
}
if(flag){
break;
}
}
if(flag){
ret += solution(y + len / 2, x + len / 2, len / 2);
}else{
ret += to_string(prev);
}
ret += ")";
// 최종압축 이후 다시 압축진행
char prevC = ret[1];
flag = 0;
for (char ch : ret){
if(ch == '(' || ch == ')'){
continue;
}
if(prevC != ch){
flag = 1;
break;
}
}
if(!flag){
ret = "(";
ret += prevC;
ret += ")";
return ret;
}
return ret;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n;
string bufferflush;
getline(cin, bufferflush);
for (int i = 0; i < n; i++){
string temp;
getline(cin, temp);
for (int j = 0; j < n; j++){
quad[i][j] = temp[j] - '0';
}
}
cout << solution(0, 0, n) << "\n";
return 0;
}
- 1~4사분면 각각 쪼개어 재귀호출했는데, 56%에서 에러 걸렸음.
(1111)
과 같은 부분에 대해 에러처리를 진행해도 통과하지 못함. 놓친 로직이 있고 코드도 더럽다
#include<bits/stdc++.h>
using namespace std;
int n;
int quad[64][64];
string compress(int y, int x, int len)
{
string ret;
bool flag = 0;
int prev = quad[y][x];
if(len == 1){
return to_string(quad[y][x]);
}
for (int i = y; i < y + len; i++){
for (int j = x; j < x + len; j++){
if(prev != quad[i][j]){
flag = 1;
break;
}
}
if(flag){
break;
}
}
if(flag){
ret += "(";
ret += compress(y, x, len / 2);
ret += compress(y, x + len / 2, len / 2);
ret += compress(y + len / 2, x, len / 2);
ret += compress(y + len / 2, x + len / 2, len / 2);
ret += ")";
}else{
ret += to_string(prev);
}
return ret;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n;
string bufferflush;
getline(cin, bufferflush);
for (int i = 0; i < n; i++){
string temp;
getline(cin, temp);
for (int j = 0; j < n; j++){
quad[i][j] = temp[j] - '0';
}
}
cout << compress(0, 0, n) << "\n";
return 0;
}
- length가 1보다 크면서 모든 요소가 같으면 괄호를 붙이지 않는다.
- 순회 중인 쿼드트리 요소가 하나라도 오염됨을 파악하는 순간 플래그를 붙이고 순회를 중단한다.
- 플래그를 가지고 분기처리를 진행한다. 오염된 경우 괄호와 함께 각 사분면에 따라 압축을 진행하고, 아닌 경우 하나로 압축하여 리턴한다.