01二维背包——poj2576

/*
要求把a数组分成两个集合,两个集合人数最多差1,并且元素之和的差尽可能小 
那只要把所有可行的列出来即可
 
01二维背包,即体积是个二维数据,那么我们的背包状态也应该设为二维
dp[j][k]设为 有j个人,体积为k的状态是否可行 
第一维上限是人数的一般,第二维上限是元素总和的一半 
*/
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;
int n,a[200];
bool dp[105][505*100];

int main(){
    while(cin>>n){
        int sum=0;
        for(int i=1;i<=n;i++)cin>>a[i],sum+=a[i];
        memset(dp,0,sizeof dp);
        
        int W1=(n+1)/2,W2=sum/2;dp[0][0]=1; 
        for(int i=1;i<=n;i++)
            for(int j=W1;j>=1;j--)
                for(int k=W2;k>=a[i];k--)
                    dp[j][k]|=dp[j-1][k-a[i]];
        
        int ans=0;
        for(int k=1;k<=W2;k++)
            if(dp[W1][k])ans=max(ans,k);
        if(n%2)
            for(int k=1;k<=W2;k++)
                if(dp[W1-1][k])ans=max(ans,k);
        cout<<ans<<" "<<sum-ans<<'
';    
    }        
}
原文地址:https://www.cnblogs.com/zsben991126/p/11179716.html