P1941 飞扬的小鸟

此题很容易写出方程,由以前的知识可以迁移得,本题可以用完全背包的方法进行优化,使用滚动数组即可得到答案。
//莫名奇妙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;
	}
}
原文地址:https://www.cnblogs.com/gengchen/p/6064892.html