20230605 solution ( medic + fishing + snow + happy )
我竟然还记得填坑 感动
T1
典中典的背包板子 没啥好说的
code:
#include <bits/stdc++.h>
#define ll long long //其实不用开 但是以防万一
using namespace std;
const int N = 0x0d00;
ll f[N], g[N];
int T, M;
int main() {
scanf("%d%d", &T, &M);
for (int i = 1; i <= M; ++i) {
int t, v;
scanf("%d%d", &t, &v);
memcpy(g, f, sizeof f );
for (int j = t; j <= T; ++j) f[j] = max(g[j], g[j - t] + v);
}
printf("%lld", f[T]);
return 0;
}
T2
看起来其实有点像背包的样子 但是我还是倾向于往普通 dp 的方向想
我们考虑转移 首先第 i 个鱼塘的状态一定是由第 i - 1 个鱼塘转移过来
然后我们考虑状态之间的关系 发现我们可以枚举离开第 i - 1 个鱼塘的时间 那么就会对第 i 个鱼塘的后面一段区间有影响
我们可以维护在第 i 个鱼塘钓 j 分钟鱼的收获
这里选择刷表转移 有两个需要注意的点:
- 刷表要把 i + 1 行一直到 T 全部刷满 即就算没鱼可钓也要转移 防止后续转移出现问题
- 可以选择在这个鱼塘啥也不调 所以枚举钓鱼时间要从 0 开始
code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 0x0d00;
const int M = 101;
ll f[M][N];
ll val[M][N];
int t[M], rel[M], maxtime[M];
int n, T;
ll ans;
void init() {
for (int i = 1; i <= n; ++i) {
maxtime[i] = 1 + val[i][1] / rel[i];
// cout << maxtime[i] << endl;
for (int j = 2; j <= maxtime[i]; ++j) val[i][j] = val[i][j - 1] - rel[i];
for (int j = 2; j <= T; ++j) val[i][j] += val[i][j - 1];
// cout << endl;
}
}
void dp() {
int st = 0;
for (int i = 0; i < n; ++i) {
st += t[i];
for (int j = st; j <= T; ++j) {
for (int k = 0; k + j + t[i + 1] <= T; ++k) {
// if (i == 1 && j + k + t[i] == 1) cout << j << " " << k << " " << t[i] << endl;
f[i + 1][j + k + t[i + 1]] = max(f[i + 1][j + k + t[i + 1]], f[i][j] + val[i + 1][k]);
ans = max(ans, f[i + 1][j + k + t[i + 1]]);
}
}
}
}
int main() {
// scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &val[i][1]);
for (int i = 1; i <= n; ++i) scanf("%d", &rel[i]);
for (int i = 2; i <= n; ++i) scanf("%d", &t[i]);
scanf("%d", &T);
init();
dp();
// for (int i = 1; i <= n; ++i) {
// for (int j = 1; j <= T; ++j) cout << f[i][j] << " ";
// cout << endl;
// }
printf("%lld",ans);
return 0;
}
T3
超级大毒瘤 题干没翻译明白而且还漏信息
原题一定保证是一个回路 并且一条道要扫两遍
所以直接计算所有道路的长度然后乘 2 除时间即可
但是这个不像原题有那个奇怪的多测 赢!
code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
double ans;
void work() {
ans *= 2;
ans /= 1000;
double time = ans / 20.0;
ll h = floor(time);
ll m = round((time - h) * 60);
if (m == 60) {
m = 0;
++h;
}
printf("%lld:%lld",h,m);
}
int main() {
freopen("data.txt", "r", stdin);
ll x, y;
scanf("%lld%lld", &x, &y);
ll x1, x2, y1, y2;
while (scanf("%lld%lld%lld%lld", &x1, &y1, &x2, &y2) != EOF) {
ans += sqrt(pow(x1 - x2, 2.0) + pow(y1 - y2, 2.0));
}
work();
return 0;
}
T4
小清新背包类板子题 也没啥好说的
code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 0721;
ll f[N], g[N];
int m, n;
int main() {
scanf("%d%d", &m, &n);
for (int i = 1; i <= n; ++i) {
int val, imp;
scanf("%d%d", &val, &imp);
memcpy(g, f, sizeof f );
for (int j = val; j <= m; ++j) f[j] = max(g[j], g[j - val] + val * imp);
}
printf("%lld",f[m]);
return 0;
}