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;
}

浙公网安备 33010602011771号