题目大意:
给你一个序列(长度小于等于200),你需要把它分成两半而且两个被分开的序列长度差不超过一(如果是偶数的话那么就必须是一样长咯)
要求分成的两个序列的总和差的绝对值最小
做题思路:
1.既然是序列总和,而且分成两半,那么我为什么不先预处理出一开始整个序列的和呢?
2.既然是两个序列的总和,那么必然会存在一个序列的总和小于等于另外一个序列的总和
感性理解:两个里面肯定有一个大的咯
3.那么我们不妨让那个小的尽可能接近总和的一半?问题就转化为了以整个序列的总和的一半为背包容量,而且限制一定要取n/2或者n/2+1个数(对其取max)?
事实证明我的思路是正确的,但是比较假的就是我只有70分,大的数据点能过,但是有几个小的数据点反而过不了,我想下载数据但是下不了,也不知道自己为什么被hack了。。。
#include <bits/stdc++.h> using namespace std; int n,a[350],sum=0; int dp[8005][105]; int main(){ cin>>n; for (int i = 1 ; i <= n ; i ++)cin>>a[i],sum+=a[i]; for (int i = 1 ; i <= n; i ++) for (int k = n/2+1; k >= 1; k-- ) for (int j = sum/2 ; j >= a[i] ; j --) dp[j][k]=max(dp[j-a[i]][k-1]+a[i],dp[j][k]); if(n%2 ==0)cout<<dp[sum/2][n/2]<<" "<<sum-dp[sum/2][n/2]; if(n%2 ==1){ int ans=max(dp[sum/2][n/2],dp[sum/2][n/2+1]); cout<<ans<<" "<<sum-ans; } return 0; }