BAOWUNOJ平分石头
题目
题目描述
给定 N 块石头与目标数值 M,每块石头只能选或者不选,从中挑选若干块石头,使得选出石头的总质量最接近 M,输出这个总质量。
输入格式第一行两个整数 N、M;
接下来 N 行,每行一个整数,表示单块石头的质量。输出格式输出满足条件的石头总质量。
数据范围
(0 < N < 200)
(0 < M < 10000)
单块石头质量:不超过 300 的正整数
所有石头总重量上限:(200 \times 300 = 60000)
时空限制
时间限制:1 秒
内存限制:512 MB
样例输入5 10
1
2
3
4
5
样例输出10
样例解释选取 1、2、3、4 四块石头,总和恰好等于 10,与目标差值为 0,为最优解。
思路
根据题意可以看出这道题是一个典型的01背包问题
1.可以用bool数组dp来确定能否达到这个质量,并且定义一个变量sum来确定最大值,sum就是所有石头的和
2.初始化dp[0]=true,因为0是可以被确定的
3.开始01背包,如果确定dp[j-a[i]]==true,就把dp[j]=true
4.最后遍历0到sum这个区间,如果i确定就看是否小于我们的mi,如果小于ans=i
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,ans,mi=1e9;
int a[205],sum=0;
bool dp[60005];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];//求总和
}
dp[0]=true;//初始化
for(int i=1;i<=n;i++){
for(int j=sum;j>=a[i];j--){
if(dp[j-a[i]]){//如果可以达到那么dp[j]=true
dp[j]=true;
}
}
}
for(int i=0;i<=sum;i++){//遍历整个区间
if(dp[i]){//如果可以达到就看是否小于最小值
int s=abs(i-m);//求差
if(s<mi){
mi=s;
ans=i;
}
}
}
cout<<ans;
return 0;
}
这道题是一个典型的01背包模板题,很适合新手练练手感

浙公网安备 33010602011771号