[Acwing|蓝桥杯] 3417. 砝码称重 背包求方案数

前言

传送门 :

思路

如果只考虑放一边可以组合出多少种类的话,那么显然是背包组合方案数

但是这里是可以放两边的,也就是在转移的时候会出现一个 j − a [ i ] j-a[i] ja[i]有可能会出现负数

的情况。但是仔细想想,如果放左边无非就让右边的减少了重量,因此转移的时候

可以添加 a b s ( j − a [ i ] ) abs(j-a[i]) abs(ja[i])

状态表示 :
f [ i ] [ j ] f[i][j] f[i][j] i i i个物品里面选,体积是 j j j的方案数

状态计算 :
f [ i ] [ j ] + = f [ i − 1 ] [ j ] + f [ i − 1 ] [ j + a [ i ] ] + f [ i − 1 ] [ a b s ( j − a [ i ] ) ] f[i][j] +=f[i-1][j]+f[i-1][j+a[i]]+f[i-1][abs(j-a[i])] f[i][j]+=f[i1][j]+f[i1][j+a[i]]+f[i1][abs(ja[i])]

特别注意的是,我们将负数的情况转为正数,保守情况下应该开 2 e 5 2e5 2e5

CODE

const int N  = 1e5+10;
int f[110][N];
int a[N];

int n,sum;

void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum+=a[i];
	}
	
	f[0][0] = 1;
	for(int i=1;i<=n;i++){
		for(int j = 0 ;j<=sum;j++){
			f[i][j] = 
			f[i-1][j] + f[i-1][j+a[i]]+f[i-1][abs(j-a[i])];
		}
	}
	
	ll ans = 0 ;
	for(int i=1;i<=sum;i++){
		if(f[n][i])++ans;
	}
	cout<<ans<<endl;
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值