二维费用背包,不能使用滚动数组!
#include<iostream>
#include<cstring>
#include<cstdio>
#define max(x,y) (x>y?x:y)
using namespace std;
int f[51][23000],a[101];
int main(){
int n,i,j,k;
scanf("%d",&n);
int side=(n+1)/2,sum=0;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
sum+=a[i];
}
int halfsum=(sum+1)/2;
memset(f,0,sizeof(f));
for(i=1;i<=n;i++)
for(j=(side>i)?i:side;j>=1;j--)
for(k=halfsum;k>=a[i];k--)
f[j][k]=max(f[j][k],f[j-1][k-a[i]]+a[i]);
int ans=max(f[side][halfsum],sum-f[side][halfsum]);
printf("%d %d\n",sum-ans,ans);
return 0;
}
这样也行,初始状态的初始化注意为一个人的情况
#include<iostream>
#include<cstring>
#include<cstdio>
#define max(x,y) (x>y?x:y)
using namespace std;
int a[101];
bool f[51][25000];
int main(){
int n,i,j,k;
scanf("%d",&n);
int side=(n+1)/2,sum=0;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
sum+=a[i];
}
int halfsum=(sum+1)/2;
memset(f,0,sizeof(f));
for(i=0;i<=side;i++) f[i][0]=1; //初始化要注意
for(i=1;i<=n;i++)
for(j=(side>i)?i:side;j>=1;j--) //究竟有没有必要倒序呢?看到别人都是正序循环的
for(k=halfsum;k>=a[i];k--)
if(f[j-1][k-a[i]])
f[j][k]=1;
while(!f[side][halfsum])
halfsum--;
int ans=max(halfsum,sum-halfsum);
printf("%d %d\n",sum-ans,ans);
return 0;
}