Big Event in HDU
题意:hdu的计算机学院要分成两个院系,原学院有多个设备,知道每种设备的价值和已有的数量,问分配已有的设备,是最公平的,求出分配后每个院分到的设备价值;
很明显的一个多重背包,由于数据小,可以转换成01背包;
多重背包代码:
#include <bits/stdc++.h>
using namespace std;
int dp[250010];
int v[100], m[100];
int main(){
int n;
while(scanf("%d", &n), n>=0){
memset(dp, 0, sizeof(dp));
int sum=0;
for(int i=1; i<=n; i++){
scanf("%d%d", &v[i], &m[i]);
sum+=v[i]*m[i];
}
int temp=sum;
sum/=2;
for(int i=1; i<=n; i++){
if(v[i]*m[i]>=sum){
for(int j=v[i]; j<=sum; j++){
dp[j]=max(dp[j], dp[j-v[i]]+v[i]);
}
}
else{
int k=1;
while(k<=m[i]){
for(int j=sum; j>=k*v[i]; j--){
dp[j]=max(dp[j], dp[j-k*v[i]]+k*v[i]);
}
m[i]-=k;
k<<=1;
}
for(int j=sum; j>=m[i]*v[i]; j--){
dp[j]=max(dp[j], dp[j-m[i]*v[i]]+m[i]*v[i]);
}
}
}
int A, B;
A=max(dp[sum], temp-dp[sum]);
B=temp-A;
printf("%d %d\n", A, B);
}
return 0;
}
01背包代码
#include <bits/stdc++.h>
using namespace std;
int dp[250010];
int v[5100];
int main(){
int N;
while(scanf("%d", &N), N>=0){
memset(dp, 0, sizeof(dp));
int cnt=0;
int sum=0;
for(int i=0; i<N; i++){
int V, M;
scanf("%d%d", &V, &M);
sum+=V*M;
for(int j=0; j<M; j++)
v[++cnt]=V;
}
int temp=sum;
sum/=2;
for(int i=1; i<=cnt; i++){
for(int j=sum; j>=v[i]; j--){
dp[j]=max(dp[j], dp[j-v[i]]+v[i]);
}
}
int A=max(dp[sum], temp-dp[sum]);
printf("%d %d\n", A, temp-A);
}
return 0;
}