0
点赞
收藏
分享

微信扫一扫

从零学算法41

全栈顾问 03-06 23:30 阅读 2

一、题目描述

P8742 [蓝桥杯 2021 省 AB] 砝码称重

二、问题简析

类似 01背包,对于每个元素,可以拿(+-)或不拿。
d p [ i + 1 ] [ j ] = dp[i + 1][j]= dp[i+1][j]= i + 1 i + 1 i+1 个元素是否可以使值为 j j j

d p [ i + 1 ] [ j ] = { t r u e , d p [ i ] [ j ]   o r   d p [ i ] [ j − A [ i ] ]   o r   d p [ i ] [ j + A [ i ] ] = = t r u e f a l s e , o t h e r s dp[i + 1][j] = \begin{cases} true &,dp[i][j]~or~dp[i][j - A[i]]~or~dp[i][j + A[i]] ==true \\ false &,others \end{cases} dp[i+1][j]={truefalse,dp[i][j] or dp[i][jA[i]] or dp[i][j+A[i]]==true,others

注:

  • 1、 d p [ i ] [ j − A [ i ] ] dp[i][j - A[i]] dp[i][jA[i]] 代表 + 这个元素。显然,j - A[i] 可能小于 0 0 0,这在数组中是不允许的。我们知道,j - A[i] 是由 i i i 个元素通过加减运算得到得,若运算符号都取反,就能得到 A[i] - j。换句话说,若 d p [ i ] [ A [ i ] − j ] = = t r u e dp[i][A[i] - j] == true dp[i][A[i]j]==true,则 d p [ i ] [ j − A [ i ] ] = = t r u e dp[i][j - A[i]] == true dp[i][jA[i]]==true。所以,我们将 d p [ i ] [ j − A [ i ] ] dp[i][j - A[i]] dp[i][jA[i]] 改写为 d p [ i ] [ a b s ( j − A [ i ] ) ] dp[i][abs(j - A[i])] dp[i][abs(jA[i])]
  • 2、 d p [ i ] [ j + A [ i ] ] dp[i][j + A[i]] dp[i][j+A[i]] 代表 - 这个元素。由题意,我们知道这些元素的最大值,就是所有元素的和 mmax。因此,j + A[i] 不可能大于 mmax。所以,访问 d p [ i ] [ j + A [ i ] ] dp[i][j + A[i]] dp[i][j+A[i]] 的前提是 j + A [ i ] < m m a x j + A[i] < mmax j+A[i]<mmax

三、AC代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int quickin(void)
{
	int ret = 0;
	bool flag = false;
	char ch = getchar();
	while (ch < '0' || ch > '9')
	{
		if (ch == '-')    flag = true;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9' && ch != EOF)
	{
		ret = ret * 10 + ch - '0';
		ch = getchar();
	}
	if (flag)    ret = -ret;
	return ret;
}

const int MAX = 1e5 + 5;
int A[105], n, mmax;
bool dp[103][MAX];

int main()
{
	#ifdef LOCAL
	freopen("test.in", "r", stdin);
	#endif
	
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> A[i];
		mmax += A[i];
	}
	
	dp[0][0] = true;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 0; j <= mmax; j++)
		{
			if (j + A[i] <= mmax)
				dp[i][j] |= dp[i - 1][j + A[i]];
			dp[i][j] |= dp[i - 1][abs(j - A[i])];
			dp[i][j] |= dp[i - 1][j];
		}
	}
	ll ans = 0;
	for (int i = 1; i <= mmax; i++)
		if (dp[n][i])
			ans++;
	cout << ans << endl;
	
	return 0;
}

举报

相关推荐

0 条评论