SDUT 2022 Spring Individual Contest - A 补题

H - Reporting on Mars

题意:

给定长度为\(N\)的序列,现在需要保证序列中长度为\(k\)的子串的乘积必须为正数,现在可以修改一些数,问最小需要修改多少数,才能满足条件

思路:

第一组长为\(k\)的子串乘积为正数,第二组长为\(k\)的子串要为正数的话,那就需要第二组的最后一个数,和第一组的第一个数的正负相同,接着往下推导,发现,下标%k相同的数,必须相同,所以按照下标%k,来进行分组
此时定义\(f(i,0/1)\)为考虑前\(i\)组,每组内的乘积为正数/负数,最少修改次数

View Code
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int n, k;
int a[N];
int dp[N][2];
int x[N], y[N];
int main() {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        a[i] /= abs(a[i]);
    }

    for (int i = 1; i <= k; i++) {
        for (int j = i; j <= n; j += k) {
            if (a[j] > 0)
                x[i]++;
            else
                y[i]++;
        }
    }
    memset(dp,0x3f,sizeof(dp));
    dp[0][0]=0;
    for (int i = 1; i <= k; i++) {
        dp[i][0] = min(dp[i - 1][0] + y[i], dp[i - 1][1] + x[i]);
        dp[i][1] = min(dp[i - 1][0] + x[i], dp[i - 1][1] + y[i]);
    }

    cout << dp[k][0] << endl;
}

B - Martian Sunrise

题意:

给定\(N\)个乐章,每个人可以学任意2个乐章的组合,你有无限个人,现在需要演奏一个音乐,问最少需要多少人?

思路:

把所有乐章的组合进行状态压缩,在进行\(dp\),定义\(f(i,j)\)为前\(i\)个乐符,用到第\(j\)种组合所需要最少多少人?
感觉是状态压缩+\(dp\)的好题,记录一下,就是处理字符串有点麻烦

View Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int M = 20;
const int N = 1e4 + 10;
const int inf = 1e18;
int n, m;
char s[10];
int id[20];
int ID[M * M];
int dp[N][M * M];
int pre[N];
int cal() {
    int len = strlen(s);
    int num = (s[0] - 'A' + 1) * 3;
    if (len == 1) return num;
    if (s[1] == '#') return num + 1;
    if (s[1] == 'b') return num + 2;
    return 0;
}
signed main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        int now = 0;
        for (int j = 0; j < 7; j++) {
            cin >> s;
            int idx = cal();
            // cout<<idx<<endl;
            now = now | (1 << idx);
        }
        id[i] = now;
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            ID[i * n + j + 1] = id[i] | id[j];
        }
    }

    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M * M; j++) {
            dp[i][j] = inf;
        }
    }
    for (int i = 0; i < N; i++) {
        pre[i] = inf;
    }

    pre[0] = 0;
    int res = inf;
    cin >> m;
    int up = n * n;
    for (int i = 1; i <= m; i++) {
        cin >> s;
        int idx = cal();
        int minv = inf;
        for (int j = 1; j <= up; j++) {
            if ((ID[j] >> idx) & 1) {
                dp[i][j] = dp[i - 1][j];
                dp[i][j] = min(dp[i][j], pre[i - 1] + 1);
                pre[i] = min(pre[i], dp[i][j]);
            }
        }
    }

    for (int i = 1; i <= up; i++) {
        res = min(res, dp[m][i]);
    }

    cout << res << endl;
}
posted @ 2022-03-02 20:40  Wraith_G  阅读(57)  评论(1)    收藏  举报
// //