1036: 分配宝藏
时间限制: 1 Sec 内存限制: 128 MB
http://acm.xidian.edu.cn/problem.php?id=1036
题目描述
两个寻宝者找到一个宝藏,里面包含着n件物品,每件物品的价值是w[i]。suma代表寻宝者A所获物品的总价值,sumb代表寻宝者B所获物品的总价值,请问怎么分配,能使得|suma - sumb|(即suma与sumb之差的绝对值)最小。
输入
有多组输入数据,第一行为一个数字T,代表有T组输入数据 (0<T<=50)。
接下来为T组数据,每组数据分为两行:
第一行有一个整数n, 表示物品个数,其中0<n<=200.
第二行有n个整数,第i个正数w[i]代表第i件物品的价值,其中0<w[i]<=200.
注意:所有数据均为正整数。
输出
输出一个整数,表示|suma-sumb|。
样例输入
4
1 2 3 4
样例输出
0
本题是典型的01背包问题,总质量的一半作为背包的容量。 当然我刚做这题的时候还没学dp,暴力搜索求解的,下面给出代码
//使用dp来做,实质上是记忆化搜索
#include<bits/stdc++.h>
using namespace std;
int w[201];
int dp[201][201];
int main(){
int n,sum=0;scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&w[i]);
sum+=w[i];
}int aver=sum/2;
for(int i=0;i<n;i++){
for(int j=0;j<=aver;j++){
if(j<w[i]){
dp[i+1][j]=dp[i][j];
}
else{
dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+w[i]);
}
}
}
printf("%d\n",abs(sum-2*dp[n][aver]));
}```
```cpp
使用暴力搜索,可能会超时
#include<bits/stdc++.h>
using namespace std;
int w[201],n,sum=0;
int solve(int i,int j){//j为剩余的容量
int res;
if(i==n){
res=0;//已经无剩余
}else if(j<w[i]){
res=solve(i+1,j);
} else{
res=max(solve(i+1,j),solve(i+1,j-w[i])+w[i]);//搜索,面对宝藏有选和不选两种,我们选出最接近sum/2的,返回的res是最接近sum/2的
}
return res;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&w[i]);
sum+=w[i];
}int aver=sum/2;
printf("%d",sum-2*solve(0,aver));
}