zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    03Qt信号与槽(2)
    01Qt中的隐式共享
    10GNU C语言函数调用
    09GNU C语言程序编译
    第一本C语言笔记(下)
    07控制器和控制卡(3)
    06控制器和控制卡(2)
    集合
    linux指令(目录类操作指令)
    面向对象三大特征
  • 原文地址:https://www.cnblogs.com/MYCui/p/13541399.html
Copyright © 2011-2022 走看看