DP----luoguP1489猫狗大战

题目大意:

给你一个序列(长度小于等于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;
}

 

posted @ 2020-08-21 15:41  MYCui  阅读(133)  评论(0编辑  收藏  举报