前言
%\%%一下出题人BPMBPMBPM
正题
题目链接:https://www.luogu.com.cn/problem/U102488
题目大意
nnn个数,选取两组(不一定要全用上)使得他们的和相等且最大。
解题思路
考虑dpdpdp,fi,jf_{i,j}fi,j表示到第iii个,差值为jjj(这里的差值是大的减去小的)。
然后有
- 不选fi,j=fi−1,jf_{i,j}=f_{i-1,j}fi,j=fi−1,j
- 加在大的那个上
fi,j+ai=fi−1,j+aif_{i,j+a_i}=f_{i-1,j}+a_ifi,j+ai=fi−1,j+ai - 加在小的那个上
fi,∣j−ai∣=fi−1,j+max{ai−j,0}f_{i,|j-a_i|}=f_{i-1,j}+max\{a_i-j,0\}fi,∣j−ai∣=fi−1,j+max{ai−j,0}
时间复杂度O(n2)O(n^2)O(n2)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5100;
int n,a[N],f[N][N];
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);memset(f,0xcf,sizeof(f));f[0][0]=0;for(int i=1;i<=n;i++){for(int j=0;j<=5000;j++){f[i][j]=max(f[i][j],f[i-1][j]);f[i][j+a[i]]=max(f[i][j+a[i]],f[i-1][j]+a[i]);f[i][abs(j-a[i])]=max(f[i][abs(j-a[i])],f[i-1][j]+max(a[i]-j,0));}}printf("%d",f[n][0]);
}