백준
백준 27499 - 레이저 쏘기
황태건
2023. 8. 5. 15:54
https://www.acmicpc.net/problem/27499
27499번: 레이저 쏘기
첫째 줄에 센서의 수 $N$ ($1 \le N \le 1\,000$), 벽의 폭 $M$ ($2 \le M \le 10\,000$), 레이저의 세기가 부족해지는 반사 횟수 $K$ $(1 \le K \le 1\,000)$가 주어진다. 이후 둘째 줄에서 $N + 1$째 줄까지 각 센서가 위
www.acmicpc.net
발상의 전환이 필요한 문제. 이걸 떠올리고 나면 생각보다 금방 풀린다. 일단 핵심부터 말하자면, 레이저를 센서를 향해 무작정 직접 쏘는 것 만이 정답은 아니다. (무작정이 포인트임)
이런 경우의 수도 존재한다.
위 그림을 이렇게 나타내면 어떨까?
센서를 벽에 한번 반사시켰더니, 레이저를 센서를 향해 직접 쏘는 꼴이 되었다.
이제 문제를 보는 시야가 바뀐다.
최대 반사 가능 횟수 K에 대해, 존재하는 N개의 센서를 벽에 K-1번 반사시킨다. 총 N*(K-1) 개의 센서가 생길 것이다.
N*(K-1) 개의 센서에 대해 원점과 센서를 잇는 직선의 기울기를 계산한다. 기울기가 같다면 K번 미만의 반사를 통해 동시에 연결할 수 있는 센서일 것이다. 나는 기울기를 map<double>을 이용해 구현했지만, double의 정밀도는 불안정한 요소가 있으므로 가능하면 정수끼리의 나눗셈을 안전하게 비교하는 다른 방식을 찾아보는 것을 권장한다.
코드
더보기
vector<int> vec_x[1001];
vector<int> vec_y;
int n, width, k;
void solve();
int main() {
cin >> n >> width >> k;
//x좌표는 n * k개 존재한다
int x, y;
for (int i = 0; i < n; i++) {
cin >> x >> y;
vec_x[i].push_back(x);
vec_y.push_back(y);
}
solve();
}
void solve() {
//n개의 센서를 벽에 k-1번 반사시킨다
int new_x;
for (int i = 0; i < n; i++) {
for (int j = 1; j < k; j++) {
new_x = j * width;
if (j % 2)
new_x = new_x + width - vec_x[i][0];
else
new_x += vec_x[i][0];
vec_x[i].push_back(new_x);
}
}
//n * k개의 점에 대해 기울기를 구한다
map<double, int> m;
int max = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
double slope = (double)vec_y[i] / vec_x[i][j];
m[slope]++;
if (m[slope] > max)
max = m[slope];
}
}
cout << max << endl;
}
그림을 더 그리면 이해하기 편할텐데 시간이 없어서 여기까지만 쓴다.