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.初始化dp0=true,因为0是可以被确定的

3.开始01背包,如果确定dpj-a\[i]==true,就把dpj=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背包模板题,很适合新手练练手感

点点赞吧QWQ