奶牛会展--01背包+下标负数偏移

Luogu 2340

奶牛会展--01背包+下标负数偏移_第1张图片

题目分析:

  • f [ i ] [ j ] 表 示 用 前 i 个 奶 牛 , 智 商 和 为 j 时 , 最 大 的 情 商 和 f[i][j]表示用前i个奶牛,智商和为j时,最大的情商和 f[i][j]ij
  • 由于 j 会 为 负 数 , 需 要 偏 移 下 标 j会为负数,需要偏移下标 j
  • 边界: f [ i ] [ j ] = − I N F , f [ 0 ] [ T ] = 0 f[i][j]=-INF,f[0][T]=0 f[i][j]=INF,f[0][T]=0
  • 转移方程:转移时不需要判断背包容量是否足够,因为可以为负
    f [ i ] [ j + T ] = m a x ( f [ i ] [ j + T ] , m a x ( f [ i − 1 ] [ j + T ] , f [ i − 1 ] [ j − c [ i ] + T ] + w [ i ] ) ) f[i][j+T]=max(f[i][j+T],max(f[i-1][j+T] ,f[i-1][j-c[i]+T]+w[i])) f[i][j+T]=max(f[i][j+T],max(f[i1][j+T],f[i1][jc[i]+T]+w[i]))
  • 计算答案: j 从 0 到 m , 如 果 f [ n ] [ j + T ] > = 0 , a n s = m a x ( a n s , j + f [ n ] [ j ] ) j从0到m,如果f[n][j+T]>=0 ,ans=max(ans,j+f[n][j]) j0mf[n][j+T]>=0,ans=max(ans,j+f[n][j])

Code:

#include 
using namespace std;
#define maxn 410
int T,m,n,c[maxn],w[maxn],f[3][405000<<1];

inline int read_() {
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9') {
		x=(x<<1)+(x<<3)+c-'0';
		c=getchar();
	}
	return x*f;
}

void readda_() {
	n=read_();
	T=0;m=0;
	for(int i=1;i<=n;++i) {
		c[i]=read_();w[i]=read_();
		if(c[i]<0) T-=c[i];
		else m+=c[i];
	}
	memset(f,-0x7f,sizeof(f));
	int pdc=-T;T+=10;
	f[0][T]=0;
	for(int i=1;i<=n;++i) {
		for(int j=pdc;j<=m;++j) {
			f[i&1][j+T]=max(f[i&1][j+T],f[(i&1)^1][j+T]);
			f[i&1][j+T]=max(f[i&1][j+T],f[(i&1)^1][j-c[i]+T]+w[i]);
		}
	}
	int ans=0;
	for(int i=0;i<=m;++i) {
		if(f[n&1][i+T]>=0) {
			ans=max(ans,i+f[n&1][i+T]);
		}
	}
	printf("%d",ans);
}

int main() {
	freopen("a.txt","r",stdin);
	readda_();
	return 0;
}

你可能感兴趣的:(01背包)