1. 程式人生 > 其它 >AcWing第20場周賽題解

AcWing第20場周賽題解

A. 3994. 水果派

題目連結:https://www.acwing.com/problem/content/3997/

題目大意:略。

解題思路:向上取整。

示例程式:

#include <bits/stdc++.h>
using namespace std;

int T, a, b, c, d, k, c1, c2;

int main() {
    cin >> T;
    while (T--) {
        cin >> a >> b >> c >> d >> k;
        c1 = (a - 1) / c + 1;
        c2 = (b - 1) / d + 1;
        if (c1 + c2 > k) cout << -1 << endl;
        else cout << c1 << " " << c2 << endl;
    }
    return 0;
}

B. 3995. 最小的和

題目連結:https://www.acwing.com/problem/content/3998/

題目大意:略。

解題思路:忽略 a 和 b 的影響,主要考慮差。貪心思想是:每次把最大的那個差減小 1。

示例程式:

#include <bits/stdc++.h>
using namespace std;

int n, k, k2, a[1010], b[1010];
priority_queue<int> que;

int main() {
    cin >> n >> k >> k2;
    k += k2;
    for (int i = 0; i < n; i++) cin >> a[i];
    for (int i = 0; i < n; i++) cin >> b[i];
    for (int i = 0; i < n; i++) {
        int c = abs(a[i] - b[i]);
        if (c) que.push(c);
    }
    while (!que.empty() && k--) {
        int u = que.top();
        que.pop();
        u--;
        if (u) que.push(u);
    }
    if (k > 0) {
        cout << k % 2 << endl;  // 注意題目裡面的“恰好”
        return 0;
    }
    long long ans = 0;
    while (!que.empty()) {
        long long t = que.top();
        que.pop();
        ans += t * t;
    }
    cout << ans << endl;
    return 0;
}

C. 3996. 塗色

題目連結:https://www.acwing.com/problem/content/3999/

題目大意:

將磚塊合併,每次操作:

  1. 任選一種顏色。
  2. 將最開始選定的起始磚塊所在連通塊中包含的所有磚塊都塗為選定顏色,

請問,至少需要多少次操作,才能使所有磚塊都具有同一種顏色。

注意,每次染色操作所涉及的連通塊必須包含所有操作開始前選定的起始磚塊。

解題思路:區間dp。

由於題目涉及 每次染色操作所涉及的連通塊必須包含所有操作開始前選定的起始磚塊

所以需要再二外增加一個維度表示染成和區間最左邊的顏色一樣還是染成和區間最右邊的顏色一樣。

示例程式:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5005;
int dp[maxn][maxn][2], n, c[maxn];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> c[i];
    for (int l = 1; l <= n; l++) {
        for (int i = 1; i+l-1 <= n; i++) {
            int j = i+l-1;
            if (l == 1) dp[i][j][0] = dp[i][j][1] = 0;
            else {
                dp[i][j][0] = min( dp[i+1][j][0] + (c[i] != c[i+1]) , dp[i+1][j][1] + (c[i] != c[j]) );
                dp[i][j][1] = min( dp[i][j-1][0] + (c[i] != c[j]) , dp[i][j-1][1] + (c[j-1] != c[j]) );
            }
        }
    }
    cout << min(dp[1][n][0], dp[1][n][1]) << endl;
    return 0;
}