본문 바로가기

Algorithm

백준 17136번 색종이 붙이기 (삼성 A형)

반응형

문제

<그림 1>과 같이 정사각형 모양을 한 다섯 종류의 색종이가 있다. 색종이의 크기는 1×1, 2×2, 3×3, 4×4, 5×5로 총 다섯 종류가 있으며, 각 종류의 색종이는 5개씩 가지고 있다.

<그림 1>

색종이를 크기가 10×10인 종이 위에 붙이려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 0 또는 1이 적혀 있다. 1이 적힌 칸은 모두 색종이로 덮여져야 한다. 색종이를 붙일 때는 종이의 경계 밖으로 나가서는 안되고, 겹쳐도 안 된다. 또, 칸의 경계와 일치하게 붙여야 한다. 0이 적힌 칸에는 색종이가 있으면 안 된다.

종이가 주어졌을 때, 1이 적힌 모든 칸을 붙이는데 필요한 색종이의 최소 개수를 구해보자.

입력

총 10개의 줄에 종이의 각 칸에 적힌 수가 주어진다.

출력

모든 1을 덮는데 필요한 색종이의 최소 개수를 출력한다. 1을 모두 덮는 것이 불가능한 경우에는 -1을 출력한다.

 

로직은 간단한 DFS였으나 런타임이 자꾸 발생하였다.

그 이유 . 기본적으로 DFS 탐색이라 하면 새로운 current 값에서 공통 자원을 탐색하는 게 주요 로직인데

만약 런타임이 발생한다면 , 같은 인덱스를 다시 참조할 필요가 있는지 생각해 보아야 한다.

 

색종이 같은 경우 자신의 위치에서 1이 존재한다면 각 5가지의 케이스에서 가능한 경우 붙이고 붙인 상태의 

종이판을 다음 차례에서 또 붙이기 위해 참조 할 때, 이미 붙여진 자리까지 또 참조할 필요가 없다.

이 부분에서 어마어마한 시간이 소요되기 때문에 하나의 인덱스에서 작업이 끝나면 같은 인덱스는 두번다시 보지 않도록 설계 해야 함.

 

for문으로 방문하지 않은 지점인 경우 DFS를 진행해라 하는 경우 같은 로직이 될 수 도 있겠으나 , 어쨌든 탐색을 하면서 조건 비교를 해야 한다는 점.

0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

 

같은 상황에서 

0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

왼쪽 위가 1로만 5개가 먼저 채워졌다고 생각해보자 그럼 그 다음 DFS에서 마지막 1이 다시 빈자리로 리셋되고 

for이 또 처음부터 돌기 때문에 그 빈자리를 다시 1이 채우고 또 5개를 다썼으니 그다음 DFS에서 빈자리가 되고

또 처음부터 돌기 때문에 또 채우고 무한 반복이 된다.

 

#include<iostream>

using namespace std;

int arr[10][10];
int size = 0;
bool visit[10][10];
int paper[5];
int mina = 987654321;
bool normal = false;



void DFS(int cur,int i, int j)
{

	if(j == 10)
	{
		DFS(cur,i+1,0);
	}
	
	if(i == 10)
	{
		if(size == 0)
		{
			normal = true;
			if(mina > cur)
			{
				mina = cur;
			}
			return;
		}
	}
	
	

			
			if(arr[i][j] && !visit[i][j])
			{
				
				if(paper[0] > 0)
				{
					if(i < 10 && j <10)
					{
						int mul = 1;
						bool flag = false;
					
						for(int k = 0; k < 1; k++)
						{
							for(int l = 0; l < 1; l++)
							{
								mul *= arr[i+k][j+l];
								if(visit[i+k][j+l])
								{
									flag = true;
									break;
								}
							}
						}
					
						if(!flag && mul)
						{
							for(int k = 0; k < 1; k++)
							{
								for(int l = 0; l < 1; l++)
								{
									visit[i+k][j+l] = true;
								}
							}
							paper[0]--;
							size -= 1;
							DFS(cur+1,i,j+1);
							size += 1;
							paper[0]++;
							for(int k = 0; k < 1; k++)
							{
								for(int l = 0; l < 1; l++)
								{
									visit[i+k][j+l] = false;
								}
							}
						}
						
				}
				}
				
				
				if(paper[1] > 0)
				{
					if(i+1 < 10 && j+1 <10)
					{
						int mul = 1;
						bool flag = false;
					
						for(int k = 0; k < 2; k++)
						{
							for(int l = 0; l < 2; l++)
							{
								mul *= arr[i+k][j+l];
								if(visit[i+k][j+l])
								{
									flag = true;
									break;
								}
							}
						}
					
						if(!flag && mul)
						{
							for(int k = 0; k < 2; k++)
							{
								for(int l = 0; l < 2; l++)
								{
									visit[i+k][j+l] = true;
								}
							}
							paper[1]--;
							size -= 4;
							DFS(cur+1,i,j+1);
							size += 4;
							paper[1]++;
							for(int k = 0; k < 2; k++)
							{
								for(int l = 0; l < 2; l++)
								{
									visit[i+k][j+l] = false;
								}
							}
						}
						
					}
				}
				
				if(paper[2] > 0)
				{
					if(i+2 < 10 && j+2 <10)
					{
						int mul = 1;
						bool flag = false;
					
						for(int k = 0; k < 3; k++)
						{
							for(int l = 0; l < 3; l++)
							{
								mul *= arr[i+k][j+l];
								if(visit[i+k][j+l])
								{
									flag = true;
									break;
								}
							}
						}
					
						if(!flag && mul)
						{
							for(int k = 0; k < 3; k++)
							{
								for(int l = 0; l < 3; l++)
								{
									visit[i+k][j+l] = true;
								}
							}
							paper[2]--;
							size -= 9;
							DFS(cur+1,i,j+1);
							size += 9;
							paper[2]++;
							for(int k = 0; k < 3; k++)
							{
								for(int l = 0; l < 3; l++)
								{
									visit[i+k][j+l] = false;
								}
							}
						}
						
					}
					
				} 
				
				if(paper[3] > 0)
				{
					if(i+3 < 10 && j+3 <10)
					{
						int mul = 1;
						bool flag = false;
				
						for(int k = 0; k < 4; k++)
						{
							for(int l = 0; l < 4; l++)
							{
								mul *= arr[i+k][j+l];
								if(visit[i+k][j+l])
								{
									flag = true;
									break;
								}
							}
						}	
				
						if(!flag && mul)
						{
							for(int k = 0; k < 4; k++)
							{
								for(int l = 0; l < 4; l++)
								{
									visit[i+k][j+l] = true;
								}
							}
							paper[3]--;
							size -= 16;
							DFS(cur+1,i,j+1);
							size += 16;
							paper[3]++;
							for(int k = 0; k < 4; k++)
							{
								for(int l = 0; l < 4; l++)
								{
									visit[i+k][j+l] = false;
								}	
							}
						}
					
					}
				
				
				}
			
				
				if(paper[4] > 0)
				{
					if(i+4 < 10 && j+4 <10)
					{
						int mul = 1;
						bool flag = false;
				
						for(int k = 0; k < 5; k++)
						{
							for(int l = 0; l < 5; l++)
							{
								mul *= arr[i+k][j+l];
								if(visit[i+k][j+l])
								{
									flag = true;
									break;
								}
							}
						}
				
						if(!flag && mul)
						{
							for(int k = 0; k < 5; k++)
							{
								for(int l = 0; l < 5; l++)
								{
									visit[i+k][j+l] = true;
								}
							}
							paper[4]--;
							size -= 25;
							DFS(cur+1,i,j+1);
							size += 25;
							paper[4]++;
							for(int k = 0; k < 5; k++)
							{
								for(int l = 0; l < 5; l++)
								{
									visit[i+k][j+l] = false;
								}
							}
						}
					
					}
				
				}
			
			}
			else
			{
				DFS(cur,i,j+1);
			}
	
}







int main(void)
{
	
	
	for(int i = 0; i < 10; i++)
	{
		for(int j = 0; j <10; j++)
		{
			cin >> arr[i][j];
			if(arr[i][j] == 1)
			{
				size++;
			}
		}
	}
	
	for(int i = 0; i < 5; i++)
	{
		paper[i] = 5;
	}	
	
	
	DFS(0,0,0);
	
	
	if(normal)
	{
		cout << mina << endl;
	}
	else
	{
		cout << -1 << endl;
	}
	
	
}
반응형