순환 링에서 로봇의 이동 시간 계산 로봇이 원형 경로 상의 점들 사이를 이동하며, 서로 만날 경우 방향을 반전한다. 주어진 조건 하에서 모든 점을 방문하는 데 걸리는 최소 시간을 구하는 문제이다. 이는 각 위치에서 가장 가까운 로봇까지의 이동 시간을 계산하는 것으로 복잡도를 줄일 수 있다.
#include <iostream>
#include <vector>
using namespace std;
int n, m;
vector<int> pos;
vector<int> dir;
bool visited[2000010];
int main() {
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int p; char d;
cin >> p >> d;
pos.push_back(p);
dir.push_back(d == 'R' ? 1 : -1);
}
int time = 0;
int count = 0;
for (int i = 0; i < n; ++i) {
if (!visited[i]) {
visited[i] = true;
count++;
}
}
while (count < n) {
time++;
vector<int> new_pos;
for (int i = 0; i < m; ++i) {
int next = pos[i] + dir[i];
if (next >= n) next -= n;
if (next < 0) next += n;
new_pos.push_back(next);
}
for (int p : new_pos) {
if (!visited[p]) {
visited[p] = true;
count++;
}
}
}
cout << time << endl;
return 0;
}
반지름 기준의 최적 접근: 왼쪽 오른쪽 로봇의 최단 도착 시간 비교 각 위치에 대해 왼쪽에서 오는 오른쪽 이동 로봇과 오른쪽에서 오는 왼쪽 이동 로봇 중 더 빠르게 도착하는 시간을 계산하여 전체 최대값을 찾는다.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int MAXN = 2000005;
const int INF = 1e9;
int n, m;
vector<int> left_robot(MAXN, 0); // 오른쪽에서 오는 로봇의 최종 위치
vector<int> right_robot(MAXN, 0); // 왼쪽에서 오는 로봇의 최종 위치
// 왼쪽에 있는 R 로봇이 현재 위치에 도달하는 최소 시간
int get_right_time(int r_pos, int target) {
if (r_pos == 0) return INF;
if (r_pos <= target) return target - r_pos;
return n - (r_pos - target);
}
// 오른쪽에 있는 L 로봇이 현재 위치에 도달하는 최소 시간
int get_left_time(int l_pos, int target) {
if (l_pos == 0) return INF;
if (l_pos >= target) return l_pos - target;
return n - (target - l_pos);
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int x; char op;
cin >> x >> op;
if (op == 'R') left_robot[x] = x;
else right_robot[x] = x;
}
// 왼쪽에서 오는 로봇의 전파
for (int i = 1; i <= n; ++i)
left_robot[i] = max(left_robot[i], left_robot[i-1]);
for (int i = 1; i <= n; ++i)
if (left_robot[i] == 0) left_robot[i] = left_robot[n];
// 오른쪽에서 오는 로봇의 전파
for (int i = n; i >= 1; --i)
right_robot[i] = right_robot[i+1] ? right_robot[i+1] : right_robot[i];
for (int i = n; i >= 1; --i)
if (right_robot[i] == 0) right_robot[i] = right_robot[1];
int ans = 0;
for (int i = 1; i <= n; ++i) {
int t = min(get_right_time(left_robot[i], i), get_left_time(right_robot[i], i));
ans = max(ans, t);
}
cout << ans << endl;
return 0;
}
두 점 간의 최단 거리: 움직이는 점과 정지한 점 사이의 거리 두 차원 평면에서 한 점이 일정한 방향 벡터로 연속적으로 이동할 때, 다른 고정된 점과의 최단 거리를 구하는 문제. 이는 선분 위의 점에서의 수직 거리와 끝점 거리 중 작은 값으로 결정된다.
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
struct Point {
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) {}
};
double distance(const Point& a, const Point& b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double triangle_area(const Point& A, const Point& B, const Point& C) {
double a = distance(B, C), b = distance(A, C), c = distance(A, B);
double p = (a + b + c) / 2.0;
return sqrt(p * (p - a) * (p - b) * (p - c));
}
bool is_obtuse(const Point& A, const Point& B, const Point& C) {
double a = distance(B, C), b = distance(A, C), c = distance(A, B);
return b * b > a * a + c * c;
}
double min_distance_to_segment(const Point& A, const Point& B, const Point& C) {
double d1 = distance(A, C), d2 = distance(B, C);
if (is_obtuse(C, A, B) || is_obtuse(C, B, A))
return min(d1, d2);
double area = triangle_area(A, B, C);
return 2.0 * area / distance(A, B);
}
int main() {
int n;
double x0, y0, x, y;
cin >> n >> x0 >> y0 >> x >> y;
Point target(x, y);
Point current(x0, y0);
double min_dist = 1e16;
for (int i = 0; i < n; ++i) {
double dx, dy;
cin >> dx >> dy;
Point next(current.x + dx, current.y + dy);
min_dist = min(min_dist, min_distance_to_segment(current, next, target));
current = next;
}
printf("%.8f\n", min_dist);
return 0;
}
선분 교차 여부 판단: 순환 배열 기반 조합 분석 26개의 알파벳으로 구성된 순환 배열에서, 두 선분이 교차하는 쌍의 수를 세는 문제. 각 알파벳의 시작/끝 지점을 저장하고, 한 선분의 내부에 다른 선분의 단 하나의 점이 존재하면 교차함.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<int> positions[26];
int main() {
string s;
cin >> s;
for (int i = 0; i < s.size(); ++i)
positions[s[i] - 'A'].push_back(i);
int result = 0;
for (int i = 0; i < 26; ++i) {
for (int j = i + 1; j < 26; ++j) {
int cnt = 0;
for (int pos : positions[j])
if (positions[i][0] < pos && pos < positions[i][1])
cnt++;
if (cnt == 1) result++;
}
}
cout << result << endl;
return 0;
}
원형 공간에서의 최소 이동 비용: 모든 문을 열 때의 최적 선택 n개의 우물이 원형으로 배치되어 있으며, 한 개의 문에서 시작하여 모든 소가 이동하는 총 거리를 최소화하는 문제. 각 시작 위치에 대해 전체 이동 거리를 계산하고, 최소값을 반환한다.
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> cows(n);
for (int i = 0; i < n; ++i)
cin >> cows[i];
int min_cost = INT_MAX;
for (int start = 0; start < n; ++start) {
int cost = 0;
for (int j = 1; j < n; ++j)
cost += j * cows[(start + j) % n];
min_cost = min(min_cost, cost);
}
cout << min_cost << endl;
return 0;
}
축소된 사각형 최소 면적: 점 제거 후 최소 포함 영역 주어진 점들 중 하나를 제거했을 때, 남은 점들을 포함하는 최소 사각형의 면적을 구하는 문제. 해당 점이 최대/최소 좌표에 있지 않으면 무시 가능하다.
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> x(n), y(n);
for (int i = 0; i < n; ++i)
cin >> x[i] >> y[i];
vector<int> xs = x, ys = y;
sort(xs.begin(), xs.end());
sort(ys.begin(), ys.end());
int min_area = INT_MAX;
for (int i = 0; i < n; ++i) {
int xmin = (x[i] == xs[0]) ? xs[1] : xs[0];
int xmax = (x[i] == xs[n-1]) ? xs[n-2] : xs[n-1];
int ymin = (y[i] == ys[0]) ? ys[1] : ys[0];
int ymax = (y[i] == ys[n-1]) ? ys[n-2] : ys[n-1];
min_area = min(min_area, (ymax - ymin) * (xmax - xmin));
}
cout << min_area << endl;
return 0;
}
등록된 상태 전이: 비트마스크 기반 상태 변화 모델링 n개의 전구가 있으며, 각 전구는 이전 전구의 상태에 따라 전환된다. 상태를 비트로 표현하고, 주어진 시간 이후의 상태를 출력하는 문제. 사이클 감지를 통해 반복 계산을 피한다.
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAX_STATE = 1 << 16;
int state[MAX_STATE];
int update(int s, int n) {
int res = 0;
for (int i = 0; i < n; ++i) {
int prev_bit = (s >> ((i - 1 + n) % n)) & 1;
int curr_bit = (s >> i) & 1;
res |= (curr_bit ^ prev_bit) << i;
}
return res;
}
int main() {
int n; LL m;
cin >> n >> m;
int current_state = 0;
for (int i = 0; i < n; ++i) {
int bit;
cin >> bit;
current_state |= bit << i;
}
memset(state, -1, sizeof(state));
state[current_state] = 0;
for (int step = 1; step <= m; ++step) {
current_state = update(current_state, n);
if (state[current_state] == -1) {
state[current_state] = step;
} else {
int cycle_len = step - state[current_state];
int remaining = (m - step) % cycle_len;
while (remaining--) {
current_state = update(current_state, n);
}
break;
}
}
for (int i = 0; i < n; ++i)
cout << ((current_state >> i) & 1) << "\n";
return 0;
}
직각 삼각형 최대 면적: 정렬 기반 탐색 주어진 점들 중 세 점이 같은 행/열에 있을 때 직각삼각형을 만들 수 있으며, 그 면적을 계산해 최댓값을 찾는 문제.
#include
#include
using namespace std;
struct Point {
int x, y;
};
int main() {
int n;
cin >> n;
vector points(n);
for (int i = 0; i < n; ++i)
cin >> points[i].x >> points[i].y;
int max_area = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < n; ++k) {
if (i != j && j != k && i != k) {
if (points[i].x == points[j].x && points[i].y == points[k].y) {
int width = abs(points[j].y - points[i].y);
int height = abs(points[k].x - points[i].x);
max_area = max(max_area, width * height);
}
}
}
}
}
cout << max_area << endl;
return 0;
}