본문 바로가기

알고리즘/SWEA

2117

static int N, M;
static int board[20][20];
static int d[2][2] = {
	-1, 0, //up
	1, 0 //down
};

typedef struct
{
	int y, x, len;
}info;

static bool out_of_bound(int y, int x)
{
	if (y < 0 || y >= N)
		return true;
	if (x < 0 || x >= N)
		return true;

	return false;
}

static int get_home(int k, int y, int x)
{
	int ret = 0, len = 2 * k - 1;
	queue<info> q;

	q.push({ y, x, len }); //중심,
	len -= 2;

	for (int i = 1; i < k; i++) //양 옆으로,
	{
		if (x - i >= 0)
			q.push({ y, x - i, len });
		if (x + i < N)
			q.push({ y, x + i, len });
		len -= 2;
	}

	while (q.size())
	{
		info t = q.front();
		q.pop();

		y = t.y; x = t.x;
		len = t.len;

		if (board[y][x]) //center
			ret += 1;

		for (int dir = 0; dir < 2; dir++) //위, 아래로
		{
			int cy = y;
			int cx = x;

			for (int c = 0; c < len / 2; c++) //절반의 길이 만큼,
			{
				cy += d[dir][0];
				cx += d[dir][1];
				
				if (out_of_bound(cy, cx))
					break;
				if (board[cy][cx])
					ret += 1;
			}
		}
	}

	return ret;
}

static int solution(void)
{
	int home = 0, ret = 1, profit;

	scanf("%d %d", &N, &M);
	for (int y = 0; y < N; y++)
	{
		for (int x = 0; x < N; x++)
		{
			scanf("%d", &board[y][x]);
			home += board[y][x];
		}
	}

	for (int k = 2; k < N; k++)
	{
		int operation = k * k + (k - 1)*(k - 1);

		for (int y = 0; y < N; y++)
		{
			for (int x = 0; x < N; x++)
			{
				int cnt = get_home(k, y, x);
				profit = cnt * M - operation;

				if (profit >= 0 && cnt > ret) //**손해를 보지 않고, 많은 집에 서비스 제공,
					ret = cnt;
			}
		}
	}
	profit = (home * M) - (N * N + (N - 1)*(N - 1));
	if (profit >= 0) //손해를 보지 않음,
		ret = home;
	
	return ret;
}

"손해를 보지 않으면서 홈방범 서비스를 가장 많은 집들에 제공하는 서비스 영역을 찾고,
그 때의 홈방범 서비스를 제공 받는 집들의 수" 를 구해야 한다.

문제를 제대로 읽지 않아 이익의 최대값을 구하고 있었다.

 

풀이는 다음과 같이 하였다.

먼저, k==1 인 경우는 따로 계산할 필요가 없다. 최대 1개의 집만 서비스를 이용할 수 있기 때문이다.

 

그 다음 k >= 2 인 경우에는 직접 계산해보아야 한다.

방범 서비스 영역의 중심을 배열 전체에 적용해보고, 그 때 손해가 없는지 확인하고 그 때 서비스를 집의 개수가 최대인지 확인하면 된다.

 

여기서 손해가 없다는 것은 이윤이 적어도 음수가 아니라는 것을 말한다.

그래서 profit >= 0 이 되는 것이다.

 

다음은 서비스 영역을 설정하였을 때, 해당 서비스를 이용할  수 있는 집의 개수를 세는 방법이다.

예를 들어 설명하면, k == 4 일 때는 아래와 같이 서비스 영역이 설정된다.

여기서 알 수 있는 것은 k==n 일 때, 가장 긴 라인은 2k - 1 의 길이를 갖고, 그 양옆으로는 2 만큼 길이가 줄어든다는 것이다.

그리고 가운데 행은 중심 축으로서 위, 아래로 움직이는 시작점으로 사용하였다.

그래서 코드에서 먼저 중심 좌표에 대해 먼저 확인하고, 위, 아래로 움직이면서 집이 있는지 확인 하는 것이다.

 

마지막은 k == N 일 때에 대한 것이다.

짝수에 대해서는 k == N 으로 배열 전체를 감쌀 수 없다.

그러나 홀수에 대해서는 k == N 이 되면 배열 전체를 감싸게 된다.

이러한 이유는 열의 길이가 홀수이기 때문이다.

생각해보니 solution() 에서 마지막 부분이 좀 에러라, 이러한 부분에 대한 예외처리가 필요 할 것 같다.

'알고리즘 > SWEA' 카테고리의 다른 글

8568  (0) 2021.11.08
8567  (0) 2021.11.08
5653  (0) 2021.11.08
8557  (0) 2021.11.08
8556  (0) 2021.11.08