본문 바로가기
알고리즘/백준

[백준 14658] 하늘에서 별똥별이 빗발친다 (C++)

by fortissimo 2024. 2. 25.

https://www.acmicpc.net/problem/14658

 

14658번: 하늘에서 별똥별이 빗발친다

첫째 줄에 네 정수 N, M, L, K가 주어진다. (1 ≤ N, M ≤ 500,000, 1 ≤ L ≤ 100,000, 1 ≤ K ≤ 100) N은 별똥별이 떨어지는 구역의 가로길이, M은 세로길이, L은 트램펄린의 한 변의 길이, K는 별똥별의 수를

www.acmicpc.net

 

문제


“오빠! 나 얼마만큼 사랑해?”

“널 위해서라면 저기 저 하늘의 별이라도 따다 줄 수 있어. 지금 따줄까?”

“에이, 거짓말!”

“정말이야. 한 번 봐봐!”

욱제는 하늘을 발로 차버렸다. 그랬더니 정말 별이 떨어졌다. 그런데, 정말로 별이 지구로 떨어지기 시작했다. 욱제는 지구를 지키는 정의의 용사가 되기로 결심했다.

“자기야, 나 세계를 지키고 올게. 꼭 돌아올 테니 조금만 기다려줘.”

지구의 파괴를 막기 위해서는 지표면에 떨어지는 별똥별의 수를 최소화해야 한다. 욱제는 커다란 네모난 L*L 크기의 트램펄린을 준비했다. 별똥별이 어디로 떨어질지는 이미 알고 있기 때문에, 욱제는 이 트램펄린으로 최대한 많은 별똥별을 우주로 튕겨낼 계획이다. 하지만 학교 예산으로 트램펄린을 구매하는 욱제는 이 긴급한 와중에도 예산 심의 통과를 기다리느라 바쁘다!

욱제를 도와 세계를 구하자. 최대한 많은 별똥별을 튕겨내도록 트램펄린을 배치했을 때, 지구에는 몇 개의 별똥별이 부딪히게 될까? (별똥별이 떨어지는 위치는 겹치지 않으며 별똥별은 트램펄린의 모서리에 부딪혀도 튕겨나간다!) 트램펄린은 비스듬하게 배치 할 수 없다.

 

입력


첫째 줄에 네 정수 N, M, L, K가 주어진다. (1 ≤ N, M ≤ 500,000, 1 ≤ L ≤ 100,000, 1 ≤ K ≤ 100) N은 별똥별이 떨어지는 구역의 가로길이, M은 세로길이, L은 트램펄린의 한 변의 길이, K는 별똥별의 수를 뜻한다. 이후 K개의 줄에 걸쳐 별똥별이 떨어지는 위치의 좌표 (x, y)가 주어진다. (0 ≤ x ≤ N, 0 ≤ y ≤ M)

 

출력


욱제가 트램펄린으로 최대한 많은 별똥별을 튕겨낼 때, 지구에 부딪히는 별똥별의 개수를 출력한다.

 

문제 풀이


첫번째 i 반복문으로 트램펄린의 x 축을 고정시키고, 두번째 j 반복문으로 트램펄린의 y축을 고정시킨다. 해당 좌표를 트램펄린의 좌하단으로 삼고, 세번째 k 반복문으로 별똥별들이 트램펄린의 범위에 들어가는지 확인한다.

해당 위치에서의 지구에 부딪히는 별똥별의 개수는 K개 중 트램펄린의 범위에 들어가는 수(protect)를 뺸 값이며, 전체 트램펄린 위치 중 K-protect가 최소일 때 답이 된다.

더보기
#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;

int main()
{
	cin.tie(NULL);
	ios::sync_with_stdio(false);

	int N, M, L, K;
	int x, y;
	cin >> N >> M >> L >> K;
	vector<pair<int, int>> v;
	int answer = K;
	for (int i = 0; i < K; i++)
	{
		cin >> x >> y;
		v.push_back(make_pair(x, y));
	}
	for (int i = 0; i < K; i++)
	{
		int startX = v.at(i).first;
		for (int j = 0; j < K; j++)
		{
			int startY = v.at(j).second;
			int protect = 0;
			for (int k = 0; k < K; k++)
			{
				pair<int, int> currentShootingStar = v.at(k);
				int currentX = currentShootingStar.first;
				int currentY = currentShootingStar.second;
				if (startX <= currentX && currentX <= startX+L && startY <=currentY && currentY <= startY+L)
				{
					protect++;
				}
			}
			answer = min(answer, K - protect);
		}
	}
	cout << answer << "\n";
	return 0;
}