연산자 우선순위와 뱀 이동 알고리즘 분석

연산자 우선순위 (D - Operator Precedence)

길이가 \\(2n\\)인 수열 \\(a_{2n}\\)을 찾는 문제입니다. 조건은 다음과 같습니다: \\((a_1 × a_2)+(a_3 × a_4)+\ldots+(a_{2n-1} × a_{2n})=a_1×(a_2+a_3)×\ldots×(a_{2n-2}+a_{2n-1})×a_{2n}\\)
#include <iostream>
using namespace std;

int main() {
    int n, x = 1, y = 1;
    cin >> n;
    cout << x << " " << y << endl;
    for(int i = 2; i <= n; i++) {
        if(i % 2 == 0) {
            x += 1;
        } else {
            y += 1;
        }
        cout << x << " " << y << endl;
    }
    return 0;
}

뱀 이동 (G - Snake Move)

\\(n × m\\) 크기의 맵에서 길이가 \\(k\\)인 뱀의 최소 이동 횟수를 구하는 문제입니다.
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int MAXN = 1005;
const int INF = 1e9;

int dis[MAXN * MAXN], Dis[MAXN * MAXN];
bool vis[MAXN * MAXN];
vector> adj[MAXN * MAXN];

void Dijkstra(int start) {
    priority_queue, vector>, greater>> pq;
    pq.push({0, start});
    Dis[start] = 0;
    while (!pq.empty()) {
        int u = pq.top().second;
        pq.pop();
        if (vis[u]) continue;
        vis[u] = true;
        for (auto& edge : adj[u]) {
            int v = edge.first;
            int w = edge.second;
            if (Dis[v] > Dis[u] + w) {
                Dis[v] = Dis[u] + w;
                pq.push({Dis[v], v});
            }
        }
    }
}

int main() {
    int n, m, k;
    cin >> n >> m >> k;
    int rt;
    for (int i = 1; i <= k; ++i) {
        int x, y;
        cin >> x >> y;
        int pos = (x - 1) * m + y;
        dis[pos] = i;
        if (i == 1) rt = pos;
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            char s;
            cin >> s;
            if (s == '.') {
                for (int t = 0; t < 4; ++t) {
                    int tx = i + dx[t], ty = j + dy[t];
                    if (tx >= 0 && tx < n && ty >= 0 && ty < m && s != '#') {
                        adj[(i - 1) * m + j].push_back({(tx - 1) * m + ty, 1});
                    }
                }
            }
        }
    }
    memset(Dis, 0x3f, sizeof Dis);
    Dijkstra(rt);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if (Dis[(i - 1) * m + j] != INF) {
                cout << Dis[(i - 1) * m + j] << " ";
            }
        }
        cout << "\n";
    }
    return 0;
}

설탕 달콤함 II (H - Sugar Sweet II)

\\(n\\)개의 사건 순서에서 각 사건의 기대값을 계산하는 문제입니다.
#include <iostream>
#include <vector>
using namespace std;

const int MOD = 1e9 + 7;

int fact[500005], infact[500005];

int qmi(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1) res = 1LL * res * a % MOD;
        a = 1LL * a * a % MOD;
        b >>= 1;
    }
    return res;
}

void init() {
    fact[0] = infact[0] = 1;
    for (int i = 1; i <= 500000; ++i) {
        fact[i] = 1LL * fact[i - 1] * i % MOD;
        infact[i] = 1LL * infact[i - 1] * qmi(i, MOD - 2) % MOD;
    }
}

void solve() {
    int n;
    cin >> n;
    vector<int> a(n), b(n), w(n), ans(n);
    vector<bool> f(n, false);
    vector<int> rd(n, 0), dep(n, 0);
    vector g(n);

    for (int i = 0; i < n; ++i) cin >> a[i];
    for (int i = 0; i < n; ++i) cin >> b[i], --b[i];
    for (int i = 0; i < n; ++i) cin >> w[i];

    for (int i = 0; i < n; ++i) {
        if (a[i] < a[b[i]]) {
            ans[i] = (a[i] + w[i]) % MOD;
            f[i] = true;
        } else if (a[i] >= a[b[i]] + w[b[i]]) {
            ans[i] = a[i];
        } else {
            g[i].push_back(b[i]);
            ++rd[b[i]];
        }
    }

    vector<int> tp;
    for (int i = 0; i < n; ++i) {
        if (!rd[i]) tp.push_back(i);
    }

    for (int i = 0; i < tp.size(); ++i) {
        int u = tp[i];
        for (int v : g[u]) {
            if (--rd[v] == 0) tp.push_back(v);
        }
    }

    for (int i = tp.size() - 1; i >= 0; --i) {
        int u = tp[i];
        for (int v : g[u]) {
            if (f[v]) {
                dep[u] = dep[v] + 1;
                ans[u] = (a[u] + 1LL * w[u] * fact[dep[u]] % MOD * infact[n - dep[u]] % MOD) % MOD;
                f[u] = true;
            }
        }
    }

    for (int i = 0; i < n; ++i) cout << ans[i] << " ";
    cout << "\n";
}

int main() {
    init();
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

신비한 나무 (J - Mysterious Tree)

나무가 체인 또는 클로버 형태일 때, 해당 구조를 결정하는 알고리즘입니다.
#include <iostream>
#include <vector>
using namespace std;

bool checkEdge(int x, int y, vector<int>& degree) {
    return degree[x] == 1 && degree[y] == 1;
}

int main() {
    int n;
    cin >> n;
    vector<int> degree(n + 1, 0);
    for (int i = 1; i <= n / 2 + 3; ++i) {
        int x, y;
        cin >> x >> y;
        degree[x]++;
        degree[y]++;
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = i + 1; j <= n; ++j) {
            if (checkEdge(i, j, degree)) {
                cout << "Chain" << endl;
                return 0;
            }
        }
    }
    cout << "Clover" << endl;
    return 0;
}

V-다이어그램 (M - V-Diagram)

V-형태의 수열에서 연속된 부분 수열의 평균 값을 최대화하는 문제입니다.
#include <iostream>
#include <vector>
using namespace std;

double maxAverageSubarray(vector<int>& nums) {
    double maxAvg = nums[0];
    for (int i = 1; i < nums.size(); ++i) {
        double sum = nums[i];
        for (int j = i - 1; j >= 0; --j) {
            sum += nums[j];
            maxAvg = max(maxAvg, sum / (i - j + 1));
        }
    }
    return maxAvg;
}

int main() {
    int n;
    cin >> n;
    vector<int> nums(n);
    for (int i = 0; i < n; ++i) {
        cin >> nums[i];
    }
    cout << maxAverageSubarray(nums) << endl;
    return 0;
}

태그: algorithm GraphTheory DynamicProgramming

6월 28일 01:10에 게시됨