1

· · 题解

DP。

集合划分 : 第 $i$ 个不放 $f[i][j]|=f[i][j-1]

i 个放左边 f[i][j]|=f[i-1][j-a[i]]

i 个放右边 f[i][j]|=f[i-1][j+a[i]]

由于下标可能是负数,我们需要取一个绝对值,一开始我是想用 map 代替数组做到下标可以是负数的情况,但其实没有必要,因为假设正数是右边重量大,负数是左边重量大。取一个绝对值相当于把左右盘互换,不会影响答案。

#include<bits/stdc++.h>
using namespace std;
int n,maxn;
int a[110];
int f[110][200010];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        maxn+=a[i];
    }
    f[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=maxn;j++)
        {
            f[i][j]|=f[i-1][j];
            f[i][j]|=f[i-1][abs(j-a[i])];
            f[i][j]|=f[i-1][j+a[i]];
        }
    }
    int ans=0;
    for(int i=1;i<=maxn;i++)
    {
        if(f[n][i])
        ans++;
    }
    cout<<ans;
    return 0;
}