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;
}
posted @ 2022-04-11 21:43  quanjun  阅读(28)  评论(0)    收藏  举报