P1941 飞扬的小鸟

时间:2022-08-31 20:12:56

此题很容易写出方程,由以前的知识可以迁移得,本题可以用完全背包的方法进行优化,使用滚动数组即可得到答案。

//莫名奇妙60分。不知道什么细节出了错。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10005;
int main() {
// freopen("input.in", "r", stdin);
int n, m, k;
cin >> n >> m >> k;
int up[maxn], down[maxn], low[maxn], high[maxn];
for(int i = 0; i < n; i++) {
cin >> up[i] >> down[i];
low[i] = 1;
high[i] = m;
}
low[n] = 1; high[n] = m;
int pip[maxn];
memset(pip, 0, sizeof(pip));
for(int i = 1; i <= k; i++) {
int x, y, z;
cin >> x >> y >> z;
low[x] = y+1;
high[x] = z-1;
pip[x] = 1;
}
for(int i = 0; i <= n; i++) {
if(low[i] == 1 && high[i] == m)
high[i] = max(high[i], high[i-1] + up[i-1]);
}
int f[2][maxn];
memset(f, 127, sizeof(f));
int pre = 0, now = 1;
for(int i = 0; i <= m; i++) f[now][i] = 0;
for(int i = 1; i <= n; i++) {
swap(now, pre);
memset(f[now], 127, sizeof(f[now]));
for(int j = low[i]; j <= high[i]; j++) {
if(j+down[i-1] <= m)f[now][j] = f[pre][j+down[i-1]];
if(j-up[i-1]>=0) f[now][j] = min(f[now][j], min(f[pre][j-up[i-1]],f[now][j-up[i-1]])+1);
}
int s = 2139062143;
for(int j = m; j <= high[i]; j++) {
s = min(s, f[now][j]);
}
f[now][m] = s;
if(pip[i]) {
bool ok = false;
for(int j = low[i]; j <= high[i]; j++) {
if(f[now][j] != 2139062143) {
ok = true;
break;
}
}
if(ok) pip[i] = 2;
}
}
int ans = 0x3f3f3f;
for(int i = 1; i <= m; i++) {
ans = min(ans, f[now][i]);
}
if(ans != 0x3f3f3f) {
cout << 1 << endl << ans;
}
else {
cout << 0 << endl;
int sum = 0;
for(int i = 0; i <= n; i++) {
if(pip[i] == 2) sum++;
}
cout << sum;
}
}