20230516 solution ( gas + group + drop )
T1
设 f[i][j] 代表氧气为i 氮气为j的最小重量
则有 当 i < ai && j < bi 时 f[i][j] = min(f[i][j], ci)
当 i < ai && j >= bi 时 f[i][j] = min(f[i][j], f[0][j - bi] + ci]
当 i >= ai && j < bi 时 f[i][j] = min(f[i][j], f[i - ai][0] + ci]
else f[i][j] = min(f[i - ai][j - bi] + c[i], f[i][j])
合起来就是 f[i][j] = min(f[i][j], f[max(0, i - ai)][max(0, i - bi)] + ci]
答案 f[m][n][k]
开三维数组空间约为1e7 不会MLE
时间复杂度O(mnk) 不会TLE
code :
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int f[101][101][1010]; // O N id
int m, n;
int nowm, nown;
int k;
int main() {
// memset(f, 0x3f, sizeof f );
scanf("%d%d", &m, &n);
scanf("%d", &k);
for (int num = 1; num <= k; ++num) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
nowm += a, nown += b;
for (int i = 0; i <= min(nowm, m); ++i) {
for (int j = 0; j <= min(nown, n); ++j) {
if (f[i][j][num - 1] == 0 && !(i == 0 && j == 0)) f[i][j][num] = f[max(0, i - a)][max(0, j - b)][num - 1] + c;
else f[i][j][num] = min(f[i][j][num - 1], f[max(0, i - a)][max(0, j - b)][num - 1] + c);
}
}
}
printf("%d",f[m][n][k]);
return 0;
}
T2
要保证每组最多只能拿一个 那么比如说我拿第i组第3个的时候就不要考虑拿了第1 2个的情况
那么这个时候当前状态还是由第i - 1组转移过来而不是由第i组第2个转移过来 这样就可以保证每组只拿一个
开二维数组空间为VT 不会MLE
时间复杂度O(NV) 不会TLE
code :
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll f[210][15];
int id[33][15], top[15]; //用vector更好
int w[33], c[33];
int v, n, t;
int main() {
scanf("%d%d%d", &v, &n, &t);
for (int i = 1; i <= n; ++i) {
int zu;
scanf("%d%d%d", &w[i], &c[i], &zu);
id[++top[zu]][zu] = i;
}
for (int i = 1; i <= t; ++i) {
for (int j = 1; j <= top[i]; ++j) {
int now = id[j][i];
for (int k = 0; k <= v; ++k) {
if (w[now] > k) f[k][i] = max(f[k][i - 1], f[k][i]);
else f[k][i] = max(max(f[k][i - 1], f[k][i]), f[k - w[now]][i - 1] + c[now]);
}
}
if (top[i] == 0) {
for (int k = 0; k <= v; ++k) f[k][i] = f[k][i - 1];
}
}
printf("%lld",f[v][t]);
return 0;
}
T3
直接模拟复杂度 O(DI) 显然能过
code :
#include <bits/stdc++.h>
#define ls (x << 1)
#define rs (x << 1 | 1)
using namespace std;
const int N = 1e7 + 0721;
bool pos[N];
int d, I;
int main() {
freopen("drop.in", "r", stdin);
freopen("drop.out", "w", stdout);
scanf("%d%d", &d, &I);
int x;
for (int i = 1; i <= I; ++i) {
x = 1;
for (int j = 1; j < d; ++j) {
if (pos[x]) {
pos[x] = !pos[x];
x = rs;
} else {
pos[x] = !pos[x];
x = ls;
}
}
}
printf("%d",x);
return 0;
}
补:实际上一个点被经过两次等于没被经过 所以只需要看第I个点之前有多少点到达即可 复杂度O(logD)