※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 7587번 문제인 Anagrams다.
문제는 아래 링크를 확인하자.

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

 

어떤 두 문자열이 anagram인 관계라면 각 문자열을 구성하는 문자들을 알파벳순으로 정렬했을 때 얻을 수 있는 두 문자열이 같고, 그 역 또한 성립함을 관찰하자.

 

이를 이용하면 각 문자열을 구성하는 문자들을 정렬해 얻은 문자열을 이용해 두 문자열이 anagram인 관계를 확인하는 것이 가능하다.

 

map을 이용해 문자가 정렬된 문자열 별로 가장 먼저 등장한 원본 문자열이 무엇인지, 그리고 그러한 문자열이 몇 개 등장했는지 관리해 문제를 해결하자.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
using namespace std;

int N;
map<string, int> mpidx;
int cnt[1000]; string mpstr[1000];

void solve() {
	mpidx.clear();
	memset(cnt, 0, sizeof(cnt));
	for (int i = 0; i < N; i++) {
		string s; cin >> s;
		string ss = s;
		sort(s.begin(), s.end());
		if (mpidx.count(s)) cnt[mpidx[s]]++;
		else {
			mpidx[s] = i;
			cnt[i] = 1, mpstr[i] = ss;
		}
	}
	int mx = 0, ansid;
	for (int i = 0; i < N; i++) {
		if (cnt[i] > mx) mx = cnt[i], ansid = i;
	}
	cout << mpstr[ansid] << ' ' << mx - 1 << '\n';
}

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

	cin >> N;
	while (N) {
		solve();
		cin >> N;
	}
}
728x90

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 27738번 문제인 연산자 파티다.
문제는 아래 링크를 확인하자.

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

 

\(A\)부터 \(F\)까지 값이 어떻게 주어지더라도 i만큼 right shift 연산을 수행하게 되는 시점에 \(X\)는 \(2^i\)보다 항상 작아 \(X\)의 값이 0이 됨을 관찰하자.

 

\(F\)의 값이 100만 이하이므로, 마지막으로 right shift 연산이 수행된 이후부터 주어진 연산들을 직접 시뮬레이션해 문제를 해결할 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
using namespace std;
typedef long long ll;

ll N, A, B, C, D, E, F, X;

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

	cin >> N >> A >> B >> C >> D >> E >> F;
	for (ll i = N / F * F + 1; i <= N; i++) {
		if (i % A == 0) X += i;
		if (i % B == 0) X %= i;
		if (i % C == 0) X &= i;
		if (i % D == 0) X ^= i;
		if (i % E == 0) X |= i;
		if (i % F == 0) X >>= i;
	}

	cout << X;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 12946 // C++] 육각 보드  (0) 2024.06.25
[BOJ 7587 // C++] Anagrams  (0) 2024.06.24
[BOJ 13352 // C++] 석양이 진다...  (0) 2024.06.22
[BOJ 2187 // C++] 점 고르기  (0) 2024.06.21
[BOJ 3688 // C++] 래프팅 디자인  (1) 2024.06.20

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 13352번 문제인 석양이 진다...이다.
문제는 아래 링크를 확인하자.

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

 

각각의 적이 있는 좌표를 점이라 하자.

 

점이 4개 이하이면 두 점을 잇는 두 직선을 그어 모든 점이 두 직선 위에 올라가있게 할 수 있다. 또한, 모든 점이 두 직선 위에 올라가있을 수 있다면, 5개의 점 중 적어도 세 개의 점은 같은 직선 위에 있어야 한다.(비둘기집의 원리)

 

따라서 주어진 점이 5개 이상인 경우, 다섯 개의 점을 골라 점을 적어도 3개 포함하는 직선을 찾고(없다면 "failure" 출력), 그 직선 위에 있지 않은 모든 점이 한 직선 위에 있는지를 확인해 문제를 해결하자.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <cassert>
using namespace std;
typedef long long ll;

int gcd(int x, int y) {
    if (y) return gcd(y, x % y);
    return x;
}

int N, M;
int A[100000][2];
int pp = -1, qq = -1, rr = -1;
int visited[100000];

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    cin >> N;
    if (N <= 4) {
        cout << "success";
        return 0;
    }
    for (int i = 0; i < N; i++) cin >> A[i][0] >> A[i][1];
    for (int i = 0; i < 5; i++) {
        for (int j = i + 1; j < 5; j++) {
            for (int k = j + 1; k < 5; k++) {
                int dx1 = A[i][0] - A[j][0], dy1 = A[i][1] - A[j][1];
                int dx2 = A[j][0] - A[k][0], dy2 = A[j][1] - A[k][1];
                int g1 = gcd(abs(dx1), abs(dy1)), g2 = gcd(abs(dx2), abs(dy2));
                dx1 /= g1, dy1 /= g1, dx2 /= g2, dy2 /= g2;
                if (dx1 < 0) dx1 *= -1, dy1 *= -1;
                else if (!dx1) dy1 = 1;
                if (dx2 < 0) dx2 *= -1, dy2 *= -1;
                else if (!dx2) dy2 = 1;
                if (dx1 == dx2 && dy1 == dy2) {
                    pp = i, qq = j, rr = k;
                }
            }
        }
    }
    
    if (pp < 0) {
        cout << "failure";
        return 0;
    }
    
    visited[pp] = visited[qq] = 1;
    for (int k = 0; k < N; k++) {
        if (k == pp || k == qq) continue;
        int i = pp, j = qq;
        int dx1 = A[i][0] - A[j][0], dy1 = A[i][1] - A[j][1];
        int dx2 = A[j][0] - A[k][0], dy2 = A[j][1] - A[k][1];
        int g1 = gcd(abs(dx1), abs(dy1)), g2 = gcd(abs(dx2), abs(dy2));
        dx1 /= g1, dy1 /= g1, dx2 /= g2, dy2 /= g2;
        if (dx1 < 0) dx1 *= -1, dy1 *= -1;
        else if (!dx1) dy1 = 1;
        if (dx2 < 0) dx2 *= -1, dy2 *= -1;
        else if (!dx2) dy2 = 1;
        if (dx1 == dx2 && dy1 == dy2) visited[k] = 1;
    }
    
    for (int i = 0; i < N; i++) {
        if (!visited[i]) {
            A[M][0] = A[i][0], A[M][1] = A[i][1];
            M++;
        }
    }
    
    for (int j = 1; j + 1 < M; j++) {
        int i = j - 1, k = j + 1;
        int dx1 = A[i][0] - A[j][0], dy1 = A[i][1] - A[j][1];
        int dx2 = A[j][0] - A[k][0], dy2 = A[j][1] - A[k][1];
        int g1 = gcd(abs(dx1), abs(dy1)), g2 = gcd(abs(dx2), abs(dy2));
        dx1 /= g1, dy1 /= g1, dx2 /= g2, dy2 /= g2;
        if (dx1 < 0) dx1 *= -1, dy1 *= -1;
        else if (!dx1) dy1 = 1;
        if (dx2 < 0) dx2 *= -1, dy2 *= -1;
        else if (!dx2) dy2 = 1;
        if (dx1 != dx2 || dy1 != dy2) {
            cout << "failure";
            return 0;
        }
    }
    
    cout << "success";
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 7587 // C++] Anagrams  (0) 2024.06.24
[BOJ 27738 // C++] 연산자 파티  (0) 2024.06.23
[BOJ 2187 // C++] 점 고르기  (0) 2024.06.21
[BOJ 3688 // C++] 래프팅 디자인  (1) 2024.06.20
[BOJ 22683 // C++] Square Route  (1) 2024.06.19

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 2187번 문제인 점 고르기이다.
문제는 아래 링크를 확인하자.

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

 

어떤 두 점의 두 가중치가 직사각형에 포함된 점들의 가중치 중 가장 큰 수와 작은 수가 되기 위해서는 이 두 점이 같은 직사각형 안에 있을 수 있어야 함을 관찰하자. 두 점이 같은 직사각형에 포함되어 있을 수 있는지의 여부는 두 점의 좌표의 차를 이용해 간단하게 판별할 수 있다.

 

한편, 여기서 더 나아가 같은 직사각형에 포함되어 있을 수 있는 두 점의 쌍들을 전부 살펴 그 가중치 차의 최댓값을 찾는 것으로 문제를 해결할 수 있음을 보일 수 있다. 모든 두 점의 쌍을 확인하므로 정답이 되는 경우의 두 점의 쌍을 무조건 확인하며, 답을 구성하는 경우가 아닌 모든 경우는 (1) 두 점이 직사각형의 가장 크고 작은 두 가중치를 이루지 못하거나 (2) 두 가중치의 차가 답보다 작다는 점을 이용하면 이를 어렵지 않게 보일 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
using namespace std;

int N, A, B;
int X[1000], Y[1000], C[1000];
int ans;

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

	cin >> N >> A >> B;
	for (int i = 0; i < N; i++) cin >> X[i] >> Y[i] >> C[i];
	for (int i = 0; i < N; i++) {
		for (int j = i + 1; j < N; j++) {
			if (abs(X[i] - X[j]) < A && abs(Y[i] - Y[j]) < B) {
				ans = max(ans, abs(C[i] - C[j]));
			}
		}
	}

	cout << ans;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 27738 // C++] 연산자 파티  (0) 2024.06.23
[BOJ 13352 // C++] 석양이 진다...  (0) 2024.06.22
[BOJ 3688 // C++] 래프팅 디자인  (1) 2024.06.20
[BOJ 22683 // C++] Square Route  (1) 2024.06.19
[BOJ 25140 // C++] KLIZA  (0) 2024.06.18

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 3688번 문제인 래프팅 디자인이다.
문제는 아래 링크를 확인하자.

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

 

주어지는 다각형이 볼록다각형이 아닐 수 있음에 유의하자.

 

내부 다각형과 외부 다각형 사이의 최단거리를 구하면 문제를 해결할 수 있을 것이다. 이 값을 어떻게 구할 수 있을까?

 

다각형은 선분의 집합으로 나타낼 수 있으므로, 구하고자 하는 값은 "내부 다각형을 구성하는 선분 집합"의 원소와 "외부 다각형을 구성하는 선분 집합"의 원소 사이의 최솟값으로 생각할 수 있다. 여기에서 실제로는 튜브가 동시에 접하지 못할 두 선분쌍도 골라질 수 있지만, 그러한 선분쌍의 경우 튜브가 더 작아야하게끔 하는 다각형을 구성하는 다른 선분이 존재함을 생각하면 위의 계산으로 답을 얻을 수 있다는 사실이 변하지 않는다는 점을 알 수 있다.

 

가능한 모든 내부 다각형의 선분과 외부 다각형의 선분의 쌍에 대하여 두 선분 사이의 거리의 최솟값들 중 가장 작은 값을 구해 문제를 해결하자.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <cmath>
using namespace std;
typedef long double ld;

ld func(ld X1, ld Y1, ld X2, ld Y2, ld X3, ld Y3, ld X4, ld Y4) {
	ld ret = 1000000007;
	ret = min(ret, hypotl(X1 - X3, Y1 - Y3));
	ret = min(ret, hypotl(X1 - X4, Y1 - Y4));
	ret = min(ret, hypotl(X2 - X3, Y2 - Y3));
	ret = min(ret, hypotl(X2 - X4, Y2 - Y4));

	ld P1, P2, Q1, Q2, R1, R2, P, Q, R;
	P1 = X3, P2 = Y3, Q1 = X1, Q2 = Y1, R1 = X2, R2 = Y2;
	P = (Q1 - R1) * (Q1 - R1) + (Q2 - R2) * (Q2 - R2);
	Q = (P1 - R1) * (P1 - R1) + (P2 - R2) * (P2 - R2);
	R = (P1 - Q1) * (P1 - Q1) + (P2 - Q2) * (P2 - Q2);
	if (Q < P + R && R < P + Q) {
		ld A = P1 * Q2 + Q1 * R2 + R1 * P2 - P2 * Q1 - Q2 * R1 - R2 * P1;
		ld val = abs(A / sqrtl(P));
		ret = min(ret, val);
	}

	P1 = X4, P2 = Y4, Q1 = X1, Q2 = Y1, R1 = X2, R2 = Y2;
	P = (Q1 - R1) * (Q1 - R1) + (Q2 - R2) * (Q2 - R2);
	Q = (P1 - R1) * (P1 - R1) + (P2 - R2) * (P2 - R2);
	R = (P1 - Q1) * (P1 - Q1) + (P2 - Q2) * (P2 - Q2);
	if (Q < P + R && R < P + Q) {
		ld A = P1 * Q2 + Q1 * R2 + R1 * P2 - P2 * Q1 - Q2 * R1 - R2 * P1;
		ld val = abs(A / sqrtl(P));
		ret = min(ret, val);
	}

	P1 = X1, P2 = Y1, Q1 = X3, Q2 = Y3, R1 = X4, R2 = Y4;
	P = (Q1 - R1) * (Q1 - R1) + (Q2 - R2) * (Q2 - R2);
	Q = (P1 - R1) * (P1 - R1) + (P2 - R2) * (P2 - R2);
	R = (P1 - Q1) * (P1 - Q1) + (P2 - Q2) * (P2 - Q2);
	if (Q < P + R && R < P + Q) {
		ld A = P1 * Q2 + Q1 * R2 + R1 * P2 - P2 * Q1 - Q2 * R1 - R2 * P1;
		ld val = abs(A / sqrtl(P));
		ret = min(ret, val);
	}

	P1 = X2, P2 = Y2, Q1 = X3, Q2 = Y3, R1 = X4, R2 = Y4;
	P = (Q1 - R1) * (Q1 - R1) + (Q2 - R2) * (Q2 - R2);
	Q = (P1 - R1) * (P1 - R1) + (P2 - R2) * (P2 - R2);
	R = (P1 - Q1) * (P1 - Q1) + (P2 - Q2) * (P2 - Q2);
	if (Q < P + R && R < P + Q) {
		ld A = P1 * Q2 + Q1 * R2 + R1 * P2 - P2 * Q1 - Q2 * R1 - R2 * P1;
		ld val = abs(A / sqrtl(P));
		ret = min(ret, val);
	}

	return ret;
}

int N, M;
ld A[101][2], B[101][2];

void solve() {
	ld ans = 1000000007;
	cin >> N;
	for (int i = 0; i < N; i++) cin >> A[i][0] >> A[i][1];
	A[N][0] = A[0][0], A[N][1] = A[0][1];
	cin >> M;
	for (int i = 0; i < M; i++) cin >> B[i][0] >> B[i][1];
	B[M][0] = B[0][0], B[M][1] = B[0][1];

	for (int i = 0; i < N; i++) {
		ld X1 = A[i][0], Y1 = A[i][1], X2 = A[i + 1][0], Y2 = A[i + 1][1];
		for (int j = 0; j < M; j++) {
			ld X3 = B[j][0], Y3 = B[j][1], X4 = B[j + 1][0], Y4 = B[j + 1][1];
			ans = min(ans, func(X1, Y1, X2, Y2, X3, Y3, X4, Y4));
		}
	}

	cout << ans / 2 << '\n';
}

int T;

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

	cout << fixed;
	cout.precision(10);

	cin >> T;
	while (T--) solve();
}

 

랜덤 마라톤 (Beta) · 코스 3 H번

728x90

'BOJ' 카테고리의 다른 글

[BOJ 13352 // C++] 석양이 진다...  (0) 2024.06.22
[BOJ 2187 // C++] 점 고르기  (0) 2024.06.21
[BOJ 22683 // C++] Square Route  (1) 2024.06.19
[BOJ 25140 // C++] KLIZA  (0) 2024.06.18
[BOJ 20046 // C++] Road Reconstruction  (0) 2024.06.17

※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 22683번 문제인 Square Route 이다.
문제는 아래 링크를 확인하자.

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

 

네 도로로 둘러싸인 사각형이 정사각형을 이룬다는 것과 두 x축과 평행한 도로 사이의 거리 및 두 y축과 평행한 도로 사이의 거리가 서로 같다는 것은 필요충분조건임을 확인하자.

 

따라서 가능한 모든 x축과 평행한 도로 사이의 쌍에 대하여 가능한 거리별로 몇 개의 도로 쌍이 있는지를 먼저 구한 다음, 가능한 모든 y축과 평행한 도로 사이의 쌍에 대하여 두 도로 사이의 거리와 같은 거리를 갖는 x축과 평행한 도로 사이의 쌍의 개수를 더해나가 문제를 해결할 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;

int N, M;
int A[1500], B[1500];
int cnt[1500001];
ll ans;

void solve() {
    memset(cnt, 0, sizeof(cnt));
    ans = 0;
    for (int i = 0; i < N; i++) cin >> A[i];
    for (int i = 0; i < N; i++) {
        int psum = 0;
        for (int j = i; j < N; j++) {
            psum += A[j];
            cnt[psum]++;
        }
    }
    for (int i = 0; i < M; i++) cin >> B[i];
    for (int i = 0; i < M; i++) {
        int psum = 0;
        for (int j = i; j < M; j++) {
            psum += B[j];
            ans += cnt[psum];
        }
    }
    cout << ans << '\n';
}

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

    cin >> N >> M;
    while (N) {
        solve();
        cin >> N >> M;
    }
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 2187 // C++] 점 고르기  (0) 2024.06.21
[BOJ 3688 // C++] 래프팅 디자인  (1) 2024.06.20
[BOJ 25140 // C++] KLIZA  (0) 2024.06.18
[BOJ 20046 // C++] Road Reconstruction  (0) 2024.06.17
[BOJ 13270 // C++] 피보나치 치킨  (1) 2024.06.16

+ Recent posts