#4. 背包

4030: 背包

题目内容

n n n 个物品,每个物品有大小 w i w_i wi 和价值 v i v_i vi,再给定一个整数 k k k 和背包大小 m m m,对每个 1 ≤ i ≤ n − k + 1 1 \le i \le n - k + 1 1ink+1,求出如果只能选择 i i i i + k − 1 i + k - 1 i+k1 之间的物品且选择的大小之和不超过 m m m,那么物品价值之和最大是多少。

输入格式

第一行三个整数 n , m , k n, m, k n,m,k

接下来 n n n 行每行两个整数 w i , v i w_i, v_i wi,vi

输出格式

输出一行 n − k + 1 n - k + 1 nk+1 个整数,第 i i i 个整数表示只能选择第 i i i 到第 i + k − 1 i + k - 1 i+k1 之间的物品的最大价值。
样例 1 输入
7 8 4
4 4
3 3
2 2
3 1
3 1
2 4
3 4
样例 1 输出
7 6 7 9

#include 
using namespace std;
template <typename T> void read(T &t) {
	t=0; char ch=getchar(); int f=1;
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	do { (t*=10)+=ch-'0'; ch=getchar(); } while ('0'<=ch&&ch<='9'); t*=f;
}
template <typename T> void write(T t) {
	if (t<0) { putchar('-'); write(-t); return; }
	if (t>9) write(t/10);
	putchar('0'+t%10);
}
template <typename T> void writeln(T t) { write(t); puts(""); }
#define MP make_pair
typedef long long ll;
const int maxn=5010;
int n,k,m;
int L[maxn],R[maxn],w[maxn],v[maxn];
ll f[maxn][maxn],g[maxn][maxn];
void chkmax(ll &x,ll y) { if (x<y) x=y; }
int main() {
	read(n),read(m),read(k);
	for (int i=1;i<=n;i++) read(w[i]),read(v[i]);
	for (int l=1,r;l<=n;l=r+1) {
		r=min(n,l+k-1);
		for (int i=l;i<=r;i++) {
			L[i]=l,R[i]=r;
			if (i==l) f[i][w[i]]=v[i];
			else {
				for (int j=0;j<=m;j++) {
					chkmax(f[i][j],f[i-1][j]);
					if (j>=w[i]) chkmax(f[i][j],f[i-1][j-w[i]]+v[i]);
				}
			}
			for (int j=1;j<=m;j++) chkmax(f[i][j],f[i][j-1]);
		}
		for (int i=r;i>=l;i--) {
			if (i==r) g[i][w[i]]=v[i];
			else {
				for (int j=0;j<=m;j++) {
					chkmax(g[i][j],g[i+1][j]);
					if (j>=w[i]) chkmax(g[i][j],g[i+1][j-w[i]]+v[i]);
				}
			}
			for (int j=1;j<=m;j++) chkmax(g[i][j],g[i][j-1]);
		}
	}
	for (int i=1;i<=n-k+1;i++) {
		int j=i+k-1; ll res=0;
		if (L[i]==L[j]) res=f[j][m];
		else {
			for (int v=0;v<=m;v++) chkmax(res,g[i][v]+f[j][m-v]);
		}
		printf("%lld ",res);
	} puts("");
	return 0;
}

你可能感兴趣的:(c++,算法)